// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// The fuchsia.identity.account interface uses a common pattern of wrapped structs to provide type
// safety for the various integer identifiers. The FIDL bindings for these types are currently not
// very ergonomic since all FIDL structs potentially can grow to contain handles so prohibit
// useful features like cloning. This module provides convenient and full featured alternatives for
// the wrapped structs that implement From/Into for each conversion to the FIDL type.
//
// Longer term we aspire to annotate this wrapper pattern in FIDL, which would allow the bindings
// to be more ergonomic and remove the need for this module.

use serde::de::{Deserialize, Deserializer};
use serde::Serialize;
use std::cmp::Ordering;
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};

/// Implements `$name` as a new wrapper type.
///
/// This wrapper type implements many standard copy and comparison traits and provides conversion
/// in both directions to a type with the same name in `$fidl_crate`. This type must by a struct
/// contain a single field of type `$type` named 'id'.
///
/// `$type` must implement the following traits: `Debug`, `Clone`, `Hash`, `Eq`, and `Ord`.
///
/// # Examples
///
/// ```
/// wrapper_type!(LocalAccountId, u64, fidl_fuchsia_identity_account);
/// ```
// TODO(fxbug.dev/7807): Use FIDL type aliases when exposed in the Rust bindings.
macro_rules! wrapper_type {
    ($name:ident, $type:ty) => {
        /// A simpler wrapper around the less ergonomic autogenerated FIDL type.
        pub struct $name {
            inner: $type,
        }

        impl $name {
            /// Construct a new instance from the supplied id.
            pub fn new(id: $type) -> Self {
                $name { inner: id }
            }
        }

        impl Clone for $name {
            fn clone(&self) -> $name {
                $name { inner: self.inner.clone() }
            }
        }

        impl Hash for $name {
            fn hash<H: Hasher>(&self, state: &mut H) {
                self.inner.hash(state);
            }
        }

        impl Ord for $name {
            fn cmp(&self, other: &$name) -> Ordering {
                self.inner.cmp(&other.inner)
            }
        }

        impl PartialOrd for $name {
            fn partial_cmp(&self, other: &$name) -> Option<Ordering> {
                Some(self.cmp(other))
            }
        }

        impl PartialEq for $name {
            fn eq(&self, other: &$name) -> bool {
                self.inner == other.inner
            }
        }

        impl Eq for $name {}

        impl Debug for $name {
            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
                write!(f, "{} {{ id: {:?} }}", stringify!($name), self.inner)
            }
        }

        impl From<$type> for $name {
            fn from(fidl_type: $type) -> Self {
                $name { inner: fidl_type }
            }
        }

        impl From<$name> for $type {
            fn from(wrapper: $name) -> Self {
                wrapper.inner
            }
        }

        impl AsRef<$type> for $name {
            fn as_ref(&self) -> &$type {
                &self.inner
            }
        }

        impl AsMut<$type> for $name {
            fn as_mut(&mut self) -> &mut $type {
                &mut self.inner
            }
        }

        impl Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: ::serde::Serializer,
            {
                Serialize::serialize(&self.inner, serializer)
            }
        }

        impl<'a> Deserialize<'a> for $name {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: Deserializer<'a>,
            {
                let id = Deserialize::deserialize(deserializer)?;
                Ok($name { inner: id })
            }
        }
    };
}

wrapper_type!(LocalAccountId, u64);
/// Convenience type for the autogenerated FIDL LocalAccountId.
pub type FidlLocalAccountId = u64;

wrapper_type!(LocalPersonaId, u64);
/// Convenience type for the autogenerated FIDL LocalPersonaId.
pub type FidlLocalPersonaId = u64;

wrapper_type!(GlobalAccountId, Vec<u8>);
/// Convenience type for the autogenerated FIDL GlobalAccountId.
pub type FidlGlobalAccountId = Vec<u8>;

impl LocalAccountId {
    /// A string representing the account in a canonical way, safe for file/directory names
    pub fn to_canonical_string(&self) -> String {
        self.inner.to_string()
    }

    /// Inverse of `to_canonical_string`. Returns Some(id) if &id.to_canonical_string() == s.
    pub fn from_canonical_str(s: &str) -> Option<Self> {
        match s.parse::<u64>() {
            Ok(id) => {
                let ret = Self::new(id);
                // Double check s is the true canonical representation
                if s == &ret.to_canonical_string() {
                    Some(ret)
                } else {
                    None
                }
            }
            Err(_) => None,
        }
    }
}

impl LocalPersonaId {
    /// A string representing the persona in a canonical way, safe for file/directory names
    pub fn to_canonical_string(&self) -> String {
        self.inner.to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    // Verify a few simple properties on one of our generated types to verify the macros are
    // working. Since the generation of these types is automated we only test one.

    #[test]
    fn test_clonable() {
        let id: u64 = 456;
        let value = LocalAccountId::new(id);
        let cloned = value.clone();
        assert_eq!(id, value.inner);
        assert_eq!(id, cloned.inner);
    }

    #[test]
    fn test_debug() {
        let value = LocalAccountId::new(1111);
        assert_eq!("LocalAccountId { id: 1111 }", format!("{:?}", value));
    }

    #[test]
    fn test_eq() {
        let val_1 = LocalAccountId::new(4231);
        let val_2 = LocalAccountId::new(4231);
        assert_eq!(val_1, val_2);
    }

    #[test]
    fn test_ne() {
        let val_1 = LocalAccountId::new(554);
        let val_2 = LocalAccountId::new(555);
        assert_ne!(val_1, val_2);
    }

    #[test]
    fn test_ord() {
        let val_1 = LocalAccountId::new(333);
        let val_2 = LocalAccountId::new(444);
        assert!(val_1 < val_2);
    }

    #[test]
    fn test_to_primitive() {
        let value = LocalAccountId::new(333);
        assert_eq!(u64::from(value), 333u64);
    }

    #[test]
    fn test_to_canonical_string() {
        assert_eq!(&LocalAccountId::new(0).to_canonical_string(), "0");
        assert_eq!(&LocalAccountId::new(333).to_canonical_string(), "333");
        assert_eq!(
            &LocalAccountId::new(18446744073709551615).to_canonical_string(),
            "18446744073709551615" // max u64
        );
    }

    #[test]
    fn test_from_canonical_str() {
        assert_eq!(LocalAccountId::from_canonical_str("0"), Some(LocalAccountId::from(0)));
        assert_eq!(LocalAccountId::from_canonical_str("333"), Some(LocalAccountId::from(333)));
        assert_eq!(
            LocalAccountId::from_canonical_str("18446744073709551615"), // max u64
            Some(LocalAccountId::from(18446744073709551615))
        );

        assert_eq!(LocalAccountId::from_canonical_str("-1"), None);
        assert_eq!(LocalAccountId::from_canonical_str("18446744073709551616"), None); // max u64 + 1
        assert_eq!(LocalAccountId::from_canonical_str("0333"), None);
        assert_eq!(LocalAccountId::from_canonical_str(" 333"), None);
        assert_eq!(LocalAccountId::from_canonical_str(" "), None);
        assert_eq!(LocalAccountId::from_canonical_str(""), None);
        assert_eq!(LocalAccountId::from_canonical_str("333 "), None);
    }
}
