//! Custom field data types — the declarative "what is updateable" layer.
//!
//! A field's *type* declares its policy. The `#[entity]` macro recognises these
//! wrappers by their identifier and records the policy in the JSON manifest:
//!
//! | Type           | read | update | ws  |
//! |----------------|------|--------|-----|
//! | `ReadOnly<T>`  | ✓    | ✗      | ✗   |
//! | `Updatable<T>` | ✓    | ✓      | ✗   |
//! | `Live<T>`      | ✓    | ✓      | ✓   |
//! | `Relation<T>`  | ✓    | ✗      | ✗   |
//!
//! Each wrapper is a transparent newtype: it `Deref`s to the inner `T` and
//! (de)serializes as the inner value, so using them costs nothing at runtime.

use serde::{Deserialize, Serialize};
use std::ops::{Deref, DerefMut};

macro_rules! wrapper {
    ($(#[$doc:meta])* $name:ident) => {
        $(#[$doc])*
        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
        #[serde(transparent)]
        pub struct $name<T>(pub T);

        impl<T> $name<T> {
            pub fn new(value: T) -> Self { Self(value) }
            pub fn into_inner(self) -> T { self.0 }
        }

        impl<T> Deref for $name<T> {
            type Target = T;
            fn deref(&self) -> &T { &self.0 }
        }

        impl<T> DerefMut for $name<T> {
            fn deref_mut(&mut self) -> &mut T { &mut self.0 }
        }

        impl<T> From<T> for $name<T> {
            fn from(value: T) -> Self { Self(value) }
        }
    };
}

wrapper!(
    /// Readable but never accepted by update endpoints (e.g. primary keys).
    ReadOnly
);
wrapper!(
    /// Readable and editable; changes do not raise a WebSocket alert.
    Updatable
);
wrapper!(
    /// Readable and editable; a successful change broadcasts a WebSocket alert.
    Live
);
wrapper!(
    /// A foreign-key relation to another entity (`T` is the target struct).
    Relation
);
