serde-flattened 0.1.1

A `csv` and `serde_json` extension for flattening nested structures into flat representations. This enables for example serialization/deserialization of nested data to/from CSV.
Documentation
use {
    crate::FlattenedRef,
    serde::{Serialize, ser::SerializeStruct},
    std::{cell::RefCell, collections::HashMap},
};

#[derive(Debug, Default)]
struct StaticLookup(HashMap<Box<str>, &'static str>);

impl StaticLookup {
    fn intern(&mut self, val: impl AsRef<str>) -> &'static str {
        if !self.0.contains_key(val.as_ref()) {
            self.0
                .insert(Box::from(val.as_ref()), Box::leak(Box::from(val.as_ref())));
        }
        self.0.get(val.as_ref()).expect("checked above")
    }
}

thread_local! {
    static STATIC_LOOKUP: RefCell<StaticLookup> = Default::default();
}

impl<T> Serialize for FlattenedRef<'_, T>
where
    T: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serde_json::to_value(self.0)
            .map_err(serde::ser::Error::custom)
            .map(crate::flatten_json_value::flatten::flattened)
            .and_then({
                move |v| {
                    serializer
                        .serialize_struct(std::any::type_name::<Self>(), v.len())
                        .and_then(|mut serialize_struct| {
                            v.into_iter()
                                .try_for_each(|(k, v)| {
                                    serialize_struct.serialize_field(
                                        STATIC_LOOKUP.with_borrow_mut(|static_lookup| {
                                            static_lookup.intern(k)
                                        }),
                                        &v,
                                    )
                                })
                                .and_then(|()| serialize_struct.end())
                        })
                }
            })
    }
}