// SPDX-License-Identifier: GPL-2.0

//! Unified device property interface.
//!
//! C header: [`include/linux/property.h`](srctree/include/linux/property.h)

use core::{mem::MaybeUninit, ptr};

use super::private::Sealed;
use crate::{
    alloc::KVec,
    bindings,
    error::{to_result, Result},
    fmt,
    prelude::*,
    str::{CStr, CString},
    sync::aref::ARef,
    types::Opaque,
};

/// A reference-counted fwnode_handle.
///
/// This structure represents the Rust abstraction for a
/// C `struct fwnode_handle`. This implementation abstracts the usage of an
/// already existing C `struct fwnode_handle` within Rust code that we get
/// passed from the C side.
///
/// # Invariants
///
/// A `FwNode` instance represents a valid `struct fwnode_handle` created by the
/// C portion of the kernel.
///
/// Instances of this type are always reference-counted, that is, a call to
/// `fwnode_handle_get` ensures that the allocation remains valid at least until
/// the matching call to `fwnode_handle_put`.
#[repr(transparent)]
pub struct FwNode(Opaque<bindings::fwnode_handle>);

impl FwNode {
    /// # Safety
    ///
    /// Callers must ensure that:
    /// - The reference count was incremented at least once.
    /// - They relinquish that increment. That is, if there is only one
    ///   increment, callers must not use the underlying object anymore -- it is
    ///   only safe to do so via the newly created `ARef<FwNode>`.
    unsafe fn from_raw(raw: *mut bindings::fwnode_handle) -> ARef<Self> {
        // SAFETY: As per the safety requirements of this function:
        // - `NonNull::new_unchecked`:
        //   - `raw` is not null.
        // - `ARef::from_raw`:
        //   - `raw` has an incremented refcount.
        //   - that increment is relinquished, i.e. it won't be decremented
        //     elsewhere.
        // CAST: It is safe to cast from a `*mut fwnode_handle` to
        // `*mut FwNode`, because `FwNode` is  defined as a
        // `#[repr(transparent)]` wrapper around `fwnode_handle`.
        unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(raw.cast())) }
    }

    /// Obtain the raw `struct fwnode_handle *`.
    pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle {
        self.0.get()
    }

    /// Returns `true` if `&self` is an OF node, `false` otherwise.
    pub fn is_of_node(&self) -> bool {
        // SAFETY: The type invariant of `Self` guarantees that `self.as_raw() is a pointer to a
        // valid `struct fwnode_handle`.
        unsafe { bindings::is_of_node(self.as_raw()) }
    }

    /// Returns an object that implements [`Display`](fmt::Display) for
    /// printing the name of a node.
    ///
    /// This is an alternative to the default `Display` implementation, which
    /// prints the full path.
    pub fn display_name(&self) -> impl fmt::Display + '_ {
        struct FwNodeDisplayName<'a>(&'a FwNode);

        impl fmt::Display for FwNodeDisplayName<'_> {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                // SAFETY: `self` is valid by its type invariant.
                let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) };
                if name.is_null() {
                    return Ok(());
                }
                // SAFETY:
                // - `fwnode_get_name` returns null or a valid C string.
                // - `name` was checked to be non-null.
                let name = unsafe { CStr::from_char_ptr(name) };
                fmt::Display::fmt(name, f)
            }
        }

        FwNodeDisplayName(self)
    }

    /// Checks if property is present or not.
    pub fn property_present(&self, name: &CStr) -> bool {
        // SAFETY: By the invariant of `CStr`, `name` is null-terminated.
        unsafe { bindings::fwnode_property_present(self.as_raw().cast_const(), name.as_char_ptr()) }
    }

    /// Returns firmware property `name` boolean value.
    pub fn property_read_bool(&self, name: &CStr) -> bool {
        // SAFETY:
        // - `name` is non-null and null-terminated.
        // - `self.as_raw()` is valid because `self` is valid.
        unsafe { bindings::fwnode_property_read_bool(self.as_raw(), name.as_char_ptr()) }
    }

    /// Returns the index of matching string `match_str` for firmware string
    /// property `name`.
    pub fn property_match_string(&self, name: &CStr, match_str: &CStr) -> Result<usize> {
        // SAFETY:
        // - `name` and `match_str` are non-null and null-terminated.
        // - `self.as_raw` is valid because `self` is valid.
        let ret = unsafe {
            bindings::fwnode_property_match_string(
                self.as_raw(),
                name.as_char_ptr(),
                match_str.as_char_ptr(),
            )
        };
        to_result(ret)?;
        Ok(ret as usize)
    }

    /// Returns firmware property `name` integer array values in a [`KVec`].
    pub fn property_read_array_vec<'fwnode, 'name, T: PropertyInt>(
        &'fwnode self,
        name: &'name CStr,
        len: usize,
    ) -> Result<PropertyGuard<'fwnode, 'name, KVec<T>>> {
        let mut val: KVec<T> = KVec::with_capacity(len, GFP_KERNEL)?;

        let res = T::read_array_from_fwnode_property(self, name, val.spare_capacity_mut());
        let res = match res {
            Ok(_) => {
                // SAFETY:
                // - `len` is equal to `val.capacity - val.len`, because
                //   `val.capacity` is `len` and `val.len` is zero.
                // - All elements within the interval [`0`, `len`) were initialized
                //   by `read_array_from_fwnode_property`.
                unsafe { val.inc_len(len) }
                Ok(val)
            }
            Err(e) => Err(e),
        };
        Ok(PropertyGuard {
            inner: res,
            fwnode: self,
            name,
        })
    }

    /// Returns integer array length for firmware property `name`.
    pub fn property_count_elem<T: PropertyInt>(&self, name: &CStr) -> Result<usize> {
        T::read_array_len_from_fwnode_property(self, name)
    }

    /// Returns the value of firmware property `name`.
    ///
    /// This method is generic over the type of value to read. The types that
    /// can be read are strings, integers and arrays of integers.
    ///
    /// Reading a [`KVec`] of integers is done with the separate
    /// method [`Self::property_read_array_vec`], because it takes an
    /// additional `len` argument.
    ///
    /// Reading a boolean is done with the separate method
    /// [`Self::property_read_bool`], because this operation is infallible.
    ///
    /// For more precise documentation about what types can be read, see
    /// the [implementors of Property][Property#implementors] and [its
    /// implementations on foreign types][Property#foreign-impls].
    ///
    /// # Examples
    ///
    /// ```
    /// # use kernel::{device::{Device, property::FwNode}, str::CString};
    /// fn examples(dev: &Device) -> Result {
    ///     let fwnode = dev.fwnode().ok_or(ENOENT)?;
    ///     let b: u32 = fwnode.property_read(c"some-number").required_by(dev)?;
    ///     if let Some(s) = fwnode.property_read::<CString>(c"some-str").optional() {
    ///         // ...
    ///     }
    ///     Ok(())
    /// }
    /// ```
    pub fn property_read<'fwnode, 'name, T: Property>(
        &'fwnode self,
        name: &'name CStr,
    ) -> PropertyGuard<'fwnode, 'name, T> {
        PropertyGuard {
            inner: T::read_from_fwnode_property(self, name),
            fwnode: self,
            name,
        }
    }

    /// Returns first matching named child node handle.
    pub fn get_child_by_name(&self, name: &CStr) -> Option<ARef<Self>> {
        // SAFETY: `self` and `name` are valid by their type invariants.
        let child =
            unsafe { bindings::fwnode_get_named_child_node(self.as_raw(), name.as_char_ptr()) };
        if child.is_null() {
            return None;
        }
        // SAFETY:
        // - `fwnode_get_named_child_node` returns a pointer with its refcount
        //   incremented.
        // - That increment is relinquished, i.e. the underlying object is not
        //   used anymore except via the newly created `ARef`.
        Some(unsafe { Self::from_raw(child) })
    }

    /// Returns an iterator over a node's children.
    pub fn children<'a>(&'a self) -> impl Iterator<Item = ARef<FwNode>> + 'a {
        let mut prev: Option<ARef<FwNode>> = None;

        core::iter::from_fn(move || {
            let prev_ptr = match prev.take() {
                None => ptr::null_mut(),
                Some(prev) => {
                    // We will pass `prev` to `fwnode_get_next_child_node`,
                    // which decrements its refcount, so we use
                    // `ARef::into_raw` to avoid decrementing the refcount
                    // twice.
                    let prev = ARef::into_raw(prev);
                    prev.as_ptr().cast()
                }
            };
            // SAFETY:
            // - `self.as_raw()` is valid by its type invariant.
            // - `prev_ptr` may be null, which is allowed and corresponds to
            //   getting the first child. Otherwise, `prev_ptr` is valid, as it
            //   is the stored return value from the previous invocation.
            // - `prev_ptr` has its refount incremented.
            // - The increment of `prev_ptr` is relinquished, i.e. the
            //   underlying object won't be used anymore.
            let next = unsafe { bindings::fwnode_get_next_child_node(self.as_raw(), prev_ptr) };
            if next.is_null() {
                return None;
            }
            // SAFETY:
            // - `next` is valid because `fwnode_get_next_child_node` returns a
            //   pointer with its refcount incremented.
            // - That increment is relinquished, i.e. the underlying object
            //   won't be used anymore, except via the newly created
            //   `ARef<Self>`.
            let next = unsafe { FwNode::from_raw(next) };
            prev = Some(next.clone());
            Some(next)
        })
    }

    /// Finds a reference with arguments.
    pub fn property_get_reference_args(
        &self,
        prop: &CStr,
        nargs: NArgs<'_>,
        index: u32,
    ) -> Result<FwNodeReferenceArgs> {
        let mut out_args = FwNodeReferenceArgs::default();

        let (nargs_prop, nargs) = match nargs {
            NArgs::Prop(nargs_prop) => (nargs_prop.as_char_ptr(), 0),
            NArgs::N(nargs) => (ptr::null(), nargs),
        };

        // SAFETY:
        // - `self.0.get()` is valid.
        // - `prop.as_char_ptr()` is valid and zero-terminated.
        // - `nargs_prop` is valid and zero-terminated if `nargs`
        //   is zero, otherwise it is allowed to be a null-pointer.
        // - The function upholds the type invariants of `out_args`,
        //   namely:
        //   - It may fill the field `fwnode` with a valid pointer,
        //     in which case its refcount is incremented.
        //   - It may modify the field `nargs`, in which case it
        //     initializes at least as many elements in `args`.
        let ret = unsafe {
            bindings::fwnode_property_get_reference_args(
                self.0.get(),
                prop.as_char_ptr(),
                nargs_prop,
                nargs,
                index,
                &mut out_args.0,
            )
        };
        to_result(ret)?;

        Ok(out_args)
    }
}

/// The number of arguments to request [`FwNodeReferenceArgs`].
pub enum NArgs<'a> {
    /// The name of the property of the reference indicating the number of
    /// arguments.
    Prop(&'a CStr),
    /// The known number of arguments.
    N(u32),
}

/// The return value of [`FwNode::property_get_reference_args`].
///
/// This structure represents the Rust abstraction for a C
/// `struct fwnode_reference_args` which was initialized by the C side.
///
/// # Invariants
///
/// If the field `fwnode` is valid, it owns an increment of its refcount.
///
/// The field `args` contains at least as many initialized elements as indicated
/// by the field `nargs`.
#[repr(transparent)]
#[derive(Default)]
pub struct FwNodeReferenceArgs(bindings::fwnode_reference_args);

impl Drop for FwNodeReferenceArgs {
    fn drop(&mut self) {
        if !self.0.fwnode.is_null() {
            // SAFETY:
            // - By the type invariants of `FwNodeReferenceArgs`, its field
            //   `fwnode` owns an increment of its refcount.
            // - That increment is relinquished. The underlying object won't be
            //   used anymore because we are dropping it.
            let _ = unsafe { FwNode::from_raw(self.0.fwnode) };
        }
    }
}

impl FwNodeReferenceArgs {
    /// Returns the slice of reference arguments.
    pub fn as_slice(&self) -> &[u64] {
        // SAFETY: As per the safety invariant of `FwNodeReferenceArgs`, `nargs`
        // is the minimum number of elements in `args` that is valid.
        unsafe { core::slice::from_raw_parts(self.0.args.as_ptr(), self.0.nargs as usize) }
    }

    /// Returns the number of reference arguments.
    pub fn len(&self) -> usize {
        self.0.nargs as usize
    }

    /// Returns `true` if there are no reference arguments.
    pub fn is_empty(&self) -> bool {
        self.0.nargs == 0
    }
}

impl fmt::Debug for FwNodeReferenceArgs {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self.as_slice())
    }
}

// SAFETY: Instances of `FwNode` are always reference-counted.
unsafe impl crate::sync::aref::AlwaysRefCounted for FwNode {
    fn inc_ref(&self) {
        // SAFETY: The existence of a shared reference guarantees that the
        // refcount is non-zero.
        unsafe { bindings::fwnode_handle_get(self.as_raw()) };
    }

    unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
        // SAFETY: The safety requirements guarantee that the refcount is
        // non-zero.
        unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) }
    }
}

enum Node<'a> {
    Borrowed(&'a FwNode),
    Owned(ARef<FwNode>),
}

impl fmt::Display for FwNode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // The logic here is the same as the one in lib/vsprintf.c
        // (fwnode_full_name_string).

        // SAFETY: `self.as_raw()` is valid by its type invariant.
        let num_parents = unsafe { bindings::fwnode_count_parents(self.as_raw()) };

        for depth in (0..=num_parents).rev() {
            let fwnode = if depth == 0 {
                Node::Borrowed(self)
            } else {
                // SAFETY: `self.as_raw()` is valid.
                let ptr = unsafe { bindings::fwnode_get_nth_parent(self.as_raw(), depth) };
                // SAFETY:
                // - The depth passed to `fwnode_get_nth_parent` is
                //   within the valid range, so the returned pointer is
                //   not null.
                // - The reference count was incremented by
                //   `fwnode_get_nth_parent`.
                // - That increment is relinquished to
                //   `FwNode::from_raw`.
                Node::Owned(unsafe { FwNode::from_raw(ptr) })
            };
            // Take a reference to the owned or borrowed `FwNode`.
            let fwnode: &FwNode = match &fwnode {
                Node::Borrowed(f) => f,
                Node::Owned(f) => f,
            };

            // SAFETY: `fwnode` is valid by its type invariant.
            let prefix = unsafe { bindings::fwnode_get_name_prefix(fwnode.as_raw()) };
            if !prefix.is_null() {
                // SAFETY: `fwnode_get_name_prefix` returns null or a
                // valid C string.
                let prefix = unsafe { CStr::from_char_ptr(prefix) };
                fmt::Display::fmt(prefix, f)?;
            }
            fmt::Display::fmt(&fwnode.display_name(), f)?;
        }

        Ok(())
    }
}

/// Implemented for types that can be read as properties.
///
/// This is implemented for strings, integers and arrays of integers. It's used
/// to make [`FwNode::property_read`] generic over the type of property being
/// read. There are also two dedicated methods to read other types, because they
/// require more specialized function signatures:
/// - [`property_read_bool`](FwNode::property_read_bool)
/// - [`property_read_array_vec`](FwNode::property_read_array_vec)
///
/// It must be public, because it appears in the signatures of other public
/// functions, but its methods shouldn't be used outside the kernel crate.
pub trait Property: Sized + Sealed {
    /// Used to make [`FwNode::property_read`] generic.
    fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self>;
}

impl Sealed for CString {}

impl Property for CString {
    fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> {
        let mut str: *mut u8 = ptr::null_mut();
        let pstr: *mut _ = &mut str;

        // SAFETY:
        // - `name` is non-null and null-terminated.
        // - `fwnode.as_raw` is valid because `fwnode` is valid.
        let ret = unsafe {
            bindings::fwnode_property_read_string(fwnode.as_raw(), name.as_char_ptr(), pstr.cast())
        };
        to_result(ret)?;

        // SAFETY:
        // - `pstr` is a valid pointer to a NUL-terminated C string.
        // - It is valid for at least as long as `fwnode`, but it's only used
        //   within the current function.
        // - The memory it points to is not mutated during that time.
        let str = unsafe { CStr::from_char_ptr(*pstr) };
        Ok(str.try_into()?)
    }
}

/// Implemented for all integers that can be read as properties.
///
/// This helper trait is needed on top of the existing [`Property`]
/// trait to associate the integer types of various sizes with their
/// corresponding `fwnode_property_read_*_array` functions.
///
/// It must be public, because it appears in the signatures of other public
/// functions, but its methods shouldn't be used outside the kernel crate.
pub trait PropertyInt: Copy + Sealed {
    /// Reads a property array.
    fn read_array_from_fwnode_property<'a>(
        fwnode: &FwNode,
        name: &CStr,
        out: &'a mut [MaybeUninit<Self>],
    ) -> Result<&'a mut [Self]>;

    /// Reads the length of a property array.
    fn read_array_len_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<usize>;
}
// This macro generates implementations of the traits `Property` and
// `PropertyInt` for integers of various sizes. Its input is a list
// of pairs separated by commas. The first element of the pair is the
// type of the integer, the second one is the name of its corresponding
// `fwnode_property_read_*_array` function.
macro_rules! impl_property_for_int {
    ($($int:ty: $f:ident),* $(,)?) => { $(
        impl Sealed for $int {}
        impl<const N: usize> Sealed for [$int; N] {}

        impl PropertyInt for $int {
            fn read_array_from_fwnode_property<'a>(
                fwnode: &FwNode,
                name: &CStr,
                out: &'a mut [MaybeUninit<Self>],
            ) -> Result<&'a mut [Self]> {
                // SAFETY:
                // - `fwnode`, `name` and `out` are all valid by their type
                //   invariants.
                // - `out.len()` is a valid bound for the memory pointed to by
                //   `out.as_mut_ptr()`.
                // CAST: It's ok to cast from `*mut MaybeUninit<$int>` to a
                // `*mut $int` because they have the same memory layout.
                let ret = unsafe {
                    bindings::$f(
                        fwnode.as_raw(),
                        name.as_char_ptr(),
                        out.as_mut_ptr().cast(),
                        out.len(),
                    )
                };
                to_result(ret)?;
                // SAFETY: Transmuting from `&'a mut [MaybeUninit<Self>]` to
                // `&'a mut [Self]` is sound, because the previous call to a
                // `fwnode_property_read_*_array` function (which didn't fail)
                // fully initialized the slice.
                Ok(unsafe { core::mem::transmute::<&mut [MaybeUninit<Self>], &mut [Self]>(out) })
            }

            fn read_array_len_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<usize> {
                // SAFETY:
                // - `fwnode` and `name` are valid by their type invariants.
                // - It's ok to pass a null pointer to the
                //   `fwnode_property_read_*_array` functions if `nval` is zero.
                //   This will return the length of the array.
                let ret = unsafe {
                    bindings::$f(
                        fwnode.as_raw(),
                        name.as_char_ptr(),
                        ptr::null_mut(),
                        0,
                    )
                };
                to_result(ret)?;
                Ok(ret as usize)
            }
        }

        impl Property for $int {
            fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> {
                let val: [_; 1] = <[$int; 1]>::read_from_fwnode_property(fwnode, name)?;
                Ok(val[0])
            }
        }

        impl<const N: usize> Property for [$int; N] {
            fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> {
                let mut val: [MaybeUninit<$int>; N] = [const { MaybeUninit::uninit() }; N];

                <$int>::read_array_from_fwnode_property(fwnode, name, &mut val)?;

                // SAFETY: `val` is always initialized when
                // `fwnode_property_read_*_array` is successful.
                Ok(val.map(|v| unsafe { v.assume_init() }))
            }
        }
    )* };
}
impl_property_for_int! {
    u8: fwnode_property_read_u8_array,
    u16: fwnode_property_read_u16_array,
    u32: fwnode_property_read_u32_array,
    u64: fwnode_property_read_u64_array,
    i8: fwnode_property_read_u8_array,
    i16: fwnode_property_read_u16_array,
    i32: fwnode_property_read_u32_array,
    i64: fwnode_property_read_u64_array,
}

/// A helper for reading device properties.
///
/// Use [`Self::required_by`] if a missing property is considered a bug and
/// [`Self::optional`] otherwise.
///
/// For convenience, [`Self::or`] and [`Self::or_default`] are provided.
pub struct PropertyGuard<'fwnode, 'name, T> {
    /// The result of reading the property.
    inner: Result<T>,
    /// The fwnode of the property, used for logging in the "required" case.
    fwnode: &'fwnode FwNode,
    /// The name of the property, used for logging in the "required" case.
    name: &'name CStr,
}

impl<T> PropertyGuard<'_, '_, T> {
    /// Access the property, indicating it is required.
    ///
    /// If the property is not present, the error is automatically logged. If a
    /// missing property is not an error, use [`Self::optional`] instead. The
    /// device is required to associate the log with it.
    pub fn required_by(self, dev: &super::Device) -> Result<T> {
        if self.inner.is_err() {
            dev_err!(
                dev,
                "{}: property '{}' is missing\n",
                self.fwnode,
                self.name
            );
        }
        self.inner
    }

    /// Access the property, indicating it is optional.
    ///
    /// In contrast to [`Self::required_by`], no error message is logged if
    /// the property is not present.
    pub fn optional(self) -> Option<T> {
        self.inner.ok()
    }

    /// Access the property or the specified default value.
    ///
    /// Do not pass a sentinel value as default to detect a missing property.
    /// Use [`Self::required_by`] or [`Self::optional`] instead.
    pub fn or(self, default: T) -> T {
        self.inner.unwrap_or(default)
    }
}

impl<T: Default> PropertyGuard<'_, '_, T> {
    /// Access the property or a default value.
    ///
    /// Use [`Self::or`] to specify a custom default value.
    pub fn or_default(self) -> T {
        self.inner.unwrap_or_default()
    }
}
