//! Serialization helpers

use crate::format::{CratesCacheUser, CratesUserId, CriteriaMap, FastMap, SortedMap};
use core::fmt;
use serde::{
    de::{self, value, SeqAccess, Visitor},
    Deserialize, Deserializer, Serialize, Serializer,
};
use spanned::Spanned;

/// Serde handler to allow specifying any of [], "foo", ["foo"], or ["foo", "bar"],
/// with the strings getting proper toml spans from the original source. Specifically,
/// we deserialize `Vec<Spanned<String>>`.
///
/// This needs to solve three problems:
///
/// 1. Getting spans from toml deserialization, in general
/// 2. Being able to take two very different inputs and squish them into one form
/// 3. Wiring the span machinery into that process
///
/// Problem 1 is solved by toml-rs having a [Spanned] type for this exact thing.
/// It's genuinely magic in that the deserializer just checks if it's deserializing
/// a struct with its exact magic field names and then emits two extra values for the span.
/// We fork the actual Spanned type here to make it more ergonomic/transparent
///
/// Problem 2 is solved by [string_or_vec_inner], which is based on an example in serde's
/// own docs. We create a custom visitor that can be visited with either a sequence or
/// a string. In the sequence case we just do a normal deserialization of our target.
/// In the string case we create a new Vec to wrap our string.
///
/// Problem 3 is where things get messy. Our solution to Problem 2 naturally gets spanned
/// for the sequence case, but in the string case we're "too late" to request spanning,
/// as we no longer have a deserializer, just a `str`. All we can do is emit a dummy Spanned.
///
/// Our solution to this is to recognize that in this case we have an array of one element,
/// and so a span over the entire array is just as good as a span over the element.
/// So we deserialize a `Spanned<Vec<Spanned<String>>>` and if the Vec has `len == 1`,
/// we edit the dummy inner span to equal the outer span. We then just discard the outer span
/// (or we could keep it if we decide that's useful later).
///
/// To make this a bit easier to do, we wrap Problem 2's solution in a `StringOrVec` struct,
/// deserialize `Spanned<StringOrVec>`, and then transform that into `Vec<Spanned<String>>`
pub mod string_or_vec {
    use super::*;

    /// A type using string_or_vec_inner to make it easy to wrap in Spanned.
    #[derive(Serialize, Deserialize)]
    pub struct StringOrVec(
        #[serde(default)]
        #[serde(with = "string_or_vec_inner")]
        pub Vec<Spanned<String>>,
    );

    pub fn serialize<S, T>(v: &Vec<T>, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
        T: AsRef<str> + Serialize,
    {
        if v.len() == 1 {
            s.serialize_str(v[0].as_ref())
        } else {
            v.serialize(s)
        }
    }

    pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
    where
        D: Deserializer<'de>,
        T: StringOrVecLike,
    {
        // Get a Spanned<StringOrVec> and then use it to fixup a dummy span for len == 1
        let spanned_vec = Spanned::<StringOrVec>::deserialize(deserializer)?;
        let start = Spanned::start(&spanned_vec);
        let end = Spanned::end(&spanned_vec);
        let mut vec = Spanned::into_inner(spanned_vec).0;
        if vec.len() == 1 {
            Spanned::update_span(&mut vec[0], start, end);
        }
        Ok(StringOrVecLike::convert(vec))
    }

    // Helper trait to allow non-spanned deserialization of string_or_vec.
    pub trait StringOrVecLike {
        fn convert(from: Vec<Spanned<String>>) -> Self;
    }
    impl StringOrVecLike for Vec<Spanned<String>> {
        fn convert(from: Vec<Spanned<String>>) -> Self {
            from
        }
    }
    impl StringOrVecLike for Vec<String> {
        fn convert(from: Vec<Spanned<String>>) -> Self {
            from.into_iter().map(Spanned::into_inner).collect()
        }
    }
}

/// See [string_or_vec]
pub mod string_or_vec_inner {
    use super::*;

    pub fn serialize<S>(v: &Vec<Spanned<String>>, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if v.len() == 1 {
            s.serialize_str(&v[0])
        } else {
            v.serialize(s)
        }
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Spanned<String>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct StringOrVec;

        impl<'de> Visitor<'de> for StringOrVec {
            type Value = Vec<Spanned<String>>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("string or list of strings")
            }

            fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                Ok(vec![Spanned::from(s.to_owned())])
            }

            fn visit_seq<S>(self, seq: S) -> Result<Self::Value, S::Error>
            where
                S: SeqAccess<'de>,
            {
                Deserialize::deserialize(value::SeqAccessDeserializer::new(seq))
            }
        }

        deserializer.deserialize_any(StringOrVec)
    }
}

/// Similar to the above, but distinguishes an empty list from an absent one.
///
/// Fields using these handlers must be annotated with #[serde(default)]
pub mod string_or_vec_or_none {
    use super::*;

    pub fn serialize<S>(maybe_v: &Option<Vec<Spanned<String>>>, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if let Some(v) = maybe_v {
            string_or_vec::serialize(v, s)
        } else {
            s.serialize_none()
        }
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<Spanned<String>>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        // If the value isn't present in the stream, this deserializer won't be
        // invoked at all and the #[serde(default)] will result in `None`.
        string_or_vec::deserialize(deserializer).map(Some)
    }
}

/// Allows the `Vec<String>` map value in dependency-criteria or criteria-map to
/// support `string_or_vec` semantics.
pub mod criteria_map {
    use crate::format::CriteriaName;

    use super::*;
    #[derive(Serialize, Deserialize)]
    struct Wrapper(#[serde(with = "string_or_vec")] Vec<Spanned<CriteriaName>>);

    pub fn serialize<S>(c: &CriteriaMap, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let m: SortedMap<Spanned<String>, Wrapper> = c
            .iter()
            .map(|(k, v)| (k.clone(), Wrapper(v.clone())))
            .collect();
        m.serialize(s)
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<CriteriaMap, D::Error>
    where
        D: Deserializer<'de>,
    {
        let m = SortedMap::<Spanned<String>, Wrapper>::deserialize(deserializer)?;
        Ok(m.into_iter().map(|(k, v)| (k, v.0)).collect())
    }
}

pub mod policy {
    use super::*;
    use crate::format::{PackageName, PackagePolicyEntry, Policy, PolicyEntry, VetVersion};

    const VERSION_SEPARATOR: &str = ":";

    #[derive(serde::Serialize, serde::Deserialize)]
    #[serde(transparent)]
    pub struct AllPolicies(SortedMap<String, PolicyEntry>);

    #[derive(Debug, thiserror::Error)]
    pub enum FromAllPoliciesError {
        #[error("cannot mix versioned and unversioned policies for {name}")]
        MixedVersioning { name: PackageName },
        #[error("more than one policy provided for {name}:{version}")]
        Duplicate {
            name: PackageName,
            version: VetVersion,
        },
        #[error(transparent)]
        VersionParse(#[from] crate::errors::VersionParseError),
    }

    impl std::convert::TryFrom<AllPolicies> for Policy {
        type Error = FromAllPoliciesError;

        fn try_from(value: AllPolicies) -> Result<Self, Self::Error> {
            let mut policy = Policy::default();
            for (name, entry) in value.0 {
                match name.split_once(VERSION_SEPARATOR) {
                    Some((crate_name, crate_version)) => {
                        match policy
                            .package
                            .entry(crate_name.to_owned())
                            .or_insert_with(|| PackagePolicyEntry::Versioned {
                                version: Default::default(),
                            }) {
                            PackagePolicyEntry::Versioned { version } => {
                                version.insert(crate_version.parse()?, entry);
                            }
                            PackagePolicyEntry::Unversioned(_) => {
                                return Err(FromAllPoliciesError::MixedVersioning {
                                    name: crate_name.to_owned(),
                                });
                            }
                        }
                    }
                    None => {
                        if policy
                            .package
                            .insert(name.clone(), PackagePolicyEntry::Unversioned(entry))
                            .is_some()
                        {
                            // The entry _must_ have been `PackagePolicyEntry::Versioned`, because
                            // if it were unversioned there would be no way for more than one entry
                            // to exist in the AllPolicies map.
                            return Err(FromAllPoliciesError::MixedVersioning { name });
                        }
                    }
                }
            }
            Ok(policy)
        }
    }

    impl From<Policy> for AllPolicies {
        fn from(policy: Policy) -> Self {
            let mut ret = SortedMap::default();

            for (name, v) in policy.package {
                match v {
                    PackagePolicyEntry::Versioned { version } => {
                        for (version, entry) in version {
                            ret.insert(format!("{name}{VERSION_SEPARATOR}{version}"), entry);
                        }
                    }
                    PackagePolicyEntry::Unversioned(entry) => {
                        ret.insert(name, entry);
                    }
                }
            }

            AllPolicies(ret)
        }
    }
}

pub mod audit {
    use super::*;

    use crate::format::{AuditEntry, AuditKind, CriteriaName, Delta, VersionReq, VetVersion};

    #[derive(Serialize, Deserialize)]
    #[serde(deny_unknown_fields)]
    pub struct AuditEntryAll {
        #[serde(default)]
        #[serde(skip_serializing_if = "Vec::is_empty")]
        #[serde(with = "string_or_vec")]
        who: Vec<Spanned<String>>,
        #[serde(default)]
        #[serde(with = "string_or_vec")]
        criteria: Vec<Spanned<CriteriaName>>,
        version: Option<VetVersion>,
        delta: Option<Delta>,
        violation: Option<VersionReq>,
        notes: Option<String>,
        #[serde(rename = "aggregated-from")]
        #[serde(skip_serializing_if = "Vec::is_empty")]
        #[serde(with = "string_or_vec")]
        #[serde(default)]
        pub aggregated_from: Vec<Spanned<String>>,
    }

    impl TryFrom<AuditEntryAll> for AuditEntry {
        type Error = String;
        fn try_from(val: AuditEntryAll) -> Result<AuditEntry, Self::Error> {
            let kind = match (val.version, val.delta, val.violation) {
                (Some(version), None, None) => Ok(AuditKind::Full { version }),
                (None, Some(delta), None) => {
                    if let Some(from) = delta.from {
                        Ok(AuditKind::Delta { from, to: delta.to })
                    } else {
                        Err("'delta' must be a delta of the form 'VERSION -> VERSION'".to_string())
                    }
                }
                (None, None, Some(violation)) => Ok(AuditKind::Violation { violation }),
                _ => Err(
                    "audit entires must have exactly one of 'version', 'delta', and 'violation'"
                        .to_string(),
                ),
            };
            Ok(AuditEntry {
                who: val.who,
                notes: val.notes,
                criteria: val.criteria,
                kind: kind?,
                aggregated_from: val.aggregated_from,
                // By default, always read entries as non-fresh. The import code
                // will set this flag to true for imported entries.
                is_fresh_import: false,
            })
        }
    }

    impl From<AuditEntry> for AuditEntryAll {
        fn from(val: AuditEntry) -> AuditEntryAll {
            let (version, delta, violation) = match val.kind {
                AuditKind::Full { version } => (Some(version), None, None),
                AuditKind::Delta { from, to } => (
                    None,
                    Some(Delta {
                        from: Some(from),
                        to,
                    }),
                    None,
                ),
                AuditKind::Violation { violation } => (None, None, Some(violation)),
            };
            AuditEntryAll {
                who: val.who,
                notes: val.notes,
                criteria: val.criteria,
                version,
                delta,
                violation,
                aggregated_from: val.aggregated_from,
            }
        }
    }
}

/// Inline arrays which have a representation longer than this will be rendered
/// over multiple lines.
const ARRAY_WRAP_THRESHOLD: usize = 80;

/// Tables which would be rendered inline (see `INLINE_TABLE_KEYS`) and have an
/// inline representation larger than this threshold will be rendered by
/// TomlFormatter as non-inline tables.
const INLINE_TABLE_THRESHOLD: usize = 120;

/// Names for tables which should be rendered inline by TomlFormatter unless
/// their inline representation exceeds `INLINE_TABLE_THRESHOLD`.
const INLINE_TABLE_KEYS: &[&str] = &["dependency-criteria"];

fn inline_length(key: &str, value: &toml_edit::Item) -> usize {
    // Length of the string " = " which will appear between the key and value.
    const DECORATION_LENGTH: usize = 3;

    // The `Display` implementation for toml_edit values will produce the final
    // serialized representation of the value in the TOML document, which we can
    // use to determine the line length in utf-8 characters.
    let value_repr = value.to_string();
    key.chars().count() + value_repr.chars().count() + DECORATION_LENGTH
}

/// Tables with these names will be rendered by TomlFormatter as inline tables,
/// rather than dotted tables unless their inline representation exceeds
/// `INLINE_TABLE_THRESHOLD` UTF-8 characters in length.
fn table_should_be_inline(key: &str, value: &toml_edit::Item) -> bool {
    if !INLINE_TABLE_KEYS.contains(&key) {
        return false;
    }
    inline_length(key, value) <= INLINE_TABLE_THRESHOLD
}

/// Serialize the given data structure as a formatted `toml_edit::Document`.
///
/// The returned document can be converted to a string or otherwise written out
/// using it's `Display` implementation.
///
/// Can fail if `T`'s implementation of `Serialize` fails.
pub fn to_formatted_toml<T>(
    val: T,
    user_info: Option<&FastMap<CratesUserId, CratesCacheUser>>,
) -> Result<toml_edit::Document, toml_edit::ser::Error>
where
    T: Serialize,
{
    use toml_edit::visit_mut::VisitMut;

    struct TomlFormatter<'a> {
        user_info: Option<&'a FastMap<CratesUserId, CratesCacheUser>>,
    }
    impl TomlFormatter<'_> {
        fn add_user_login_comments(&self, v: &mut toml_edit::Item) {
            let Some(user_info) = &self.user_info else { return };
            let Some(v) = v.as_value_mut() else { return };
            let Some(user_id) = v.as_integer() else { return };
            let Some(info) = user_info.get(&(user_id as u64)) else { return };
            v.decor_mut().set_suffix(format!(" # {}", info));
        }
    }
    impl VisitMut for TomlFormatter<'_> {
        fn visit_table_mut(&mut self, node: &mut toml_edit::Table) {
            // Hide unnecessary implicit table headers for tables containing
            // only other tables. We don't do this for empty tables as otherwise
            // they could be hidden.
            if !node.is_empty() {
                node.set_implicit(true);
            }
            let is_publisher_entry = node.get("user-login").is_some();
            for (k, v) in node.iter_mut() {
                if !table_should_be_inline(&k, v) {
                    // Try to convert the value into either a table or an array of
                    // tables if it is currently an inline table or inline array of
                    // tables.
                    *v = std::mem::take(v)
                        .into_table()
                        .map(toml_edit::Item::Table)
                        .unwrap_or_else(|i| i)
                        .into_array_of_tables()
                        .map(toml_edit::Item::ArrayOfTables)
                        .unwrap_or_else(|i| i);
                }

                // If we didn't convert the array into an array of tables above,
                // check if it would be too long and wrap it onto multiple lines
                // if it would.
                if v.is_array() && inline_length(&k, v) > ARRAY_WRAP_THRESHOLD {
                    let array = v.as_array_mut().unwrap();
                    for item in array.iter_mut() {
                        item.decor_mut().set_prefix("\n    ");
                    }
                    array.set_trailing("\n");
                    array.set_trailing_comma(true);
                }

                if k == "user-id" && !is_publisher_entry {
                    self.add_user_login_comments(v);
                }

                self.visit_item_mut(v);
            }
        }
    }

    let mut toml_document = toml_edit::ser::to_document(&val)?;
    TomlFormatter { user_info }.visit_document_mut(&mut toml_document);
    Ok(toml_document)
}

/// Deserialize the given data structure from a toml::Value, without falling
/// over due to Spanned failing to parse.
pub fn parse_from_value<T>(value: toml::Value) -> Result<T, toml::de::Error>
where
    T: for<'a> Deserialize<'a>,
{
    spanned::DISABLE_SPANNED_DESERIALIZATION.with(|disabled| {
        let prev = disabled.replace(true);
        let rv = T::deserialize(value);
        disabled.set(prev);
        rv
    })
}

pub mod spanned {
    use std::{
        borrow::Borrow,
        cell::Cell,
        cmp::Ordering,
        fmt::{self, Display},
        hash::{Hash, Hasher},
        ops::{Deref, DerefMut},
    };

    use miette::SourceSpan;
    use serde::{de, ser};

    thread_local! {
        /// Hack to work around `toml::Spanned` failing to be deserialized when
        /// used with the `toml::Value` deserializer.
        pub(super) static DISABLE_SPANNED_DESERIALIZATION: Cell<bool> = Cell::new(false);
    }

    /// A spanned value, indicating the range at which it is defined in the source.
    #[derive(Clone, Default)]
    pub struct Spanned<T> {
        start: usize,
        end: usize,
        value: T,
    }

    impl<T> Spanned<T> {
        /// Create a Spanned with a specific SourceSpan.
        pub fn with_source_span(value: T, source: SourceSpan) -> Self {
            Spanned {
                start: source.offset(),
                end: source.offset() + source.len(),
                value,
            }
        }

        /// Access the start of the span of the contained value.
        pub fn start(this: &Self) -> usize {
            this.start
        }

        /// Access the end of the span of the contained value.
        pub fn end(this: &Self) -> usize {
            this.end
        }

        /// Update the span
        pub fn update_span(this: &mut Self, start: usize, end: usize) {
            this.start = start;
            this.end = end;
        }

        /// Alter a span to a length anchored from the end.
        pub fn from_end(mut this: Self, length: usize) -> Self {
            this.start = this.end - length;
            this
        }

        /// Get the span of the contained value.
        pub fn span(this: &Self) -> SourceSpan {
            (Self::start(this)..Self::end(this)).into()
        }

        /// Consumes the spanned value and returns the contained value.
        pub fn into_inner(this: Self) -> T {
            this.value
        }
    }

    impl<T> IntoIterator for Spanned<T>
    where
        T: IntoIterator,
    {
        type IntoIter = T::IntoIter;
        type Item = T::Item;
        fn into_iter(self) -> Self::IntoIter {
            self.value.into_iter()
        }
    }

    impl<'a, T> IntoIterator for &'a Spanned<T>
    where
        &'a T: IntoIterator,
    {
        type IntoIter = <&'a T as IntoIterator>::IntoIter;
        type Item = <&'a T as IntoIterator>::Item;
        fn into_iter(self) -> Self::IntoIter {
            self.value.into_iter()
        }
    }

    impl<'a, T> IntoIterator for &'a mut Spanned<T>
    where
        &'a mut T: IntoIterator,
    {
        type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
        type Item = <&'a mut T as IntoIterator>::Item;
        fn into_iter(self) -> Self::IntoIter {
            self.value.into_iter()
        }
    }

    impl<T> fmt::Debug for Spanned<T>
    where
        T: fmt::Debug,
    {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            self.value.fmt(f)
        }
    }

    impl<T> Display for Spanned<T>
    where
        T: Display,
    {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            self.value.fmt(f)
        }
    }

    impl<T> Deref for Spanned<T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.value
        }
    }

    impl<T> DerefMut for Spanned<T> {
        fn deref_mut(&mut self) -> &mut Self::Target {
            &mut self.value
        }
    }

    impl Borrow<str> for Spanned<String> {
        fn borrow(&self) -> &str {
            self
        }
    }

    impl<T> Borrow<T> for Spanned<T> {
        fn borrow(&self) -> &T {
            self
        }
    }

    impl<T, U: ?Sized> AsRef<U> for Spanned<T>
    where
        T: AsRef<U>,
    {
        fn as_ref(&self) -> &U {
            self.value.as_ref()
        }
    }

    impl<T: PartialEq> PartialEq for Spanned<T> {
        fn eq(&self, other: &Self) -> bool {
            self.value.eq(&other.value)
        }
    }

    impl<T: PartialEq<T>> PartialEq<T> for Spanned<T> {
        fn eq(&self, other: &T) -> bool {
            self.value.eq(other)
        }
    }

    impl<T: Eq> Eq for Spanned<T> {}

    impl<T: Hash> Hash for Spanned<T> {
        fn hash<H: Hasher>(&self, state: &mut H) {
            self.value.hash(state);
        }
    }

    impl<T: PartialOrd> PartialOrd for Spanned<T> {
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
            self.value.partial_cmp(&other.value)
        }
    }

    impl<T: PartialOrd<T>> PartialOrd<T> for Spanned<T> {
        fn partial_cmp(&self, other: &T) -> Option<Ordering> {
            self.value.partial_cmp(other)
        }
    }

    impl<T: Ord> Ord for Spanned<T> {
        fn cmp(&self, other: &Self) -> Ordering {
            self.value.cmp(&other.value)
        }
    }

    impl<T> From<T> for Spanned<T> {
        fn from(value: T) -> Self {
            Self {
                start: 0,
                end: 0,
                value,
            }
        }
    }

    impl<T> From<toml::Spanned<T>> for Spanned<T> {
        fn from(value: toml::Spanned<T>) -> Self {
            Self {
                start: value.start(),
                end: value.end(),
                value: value.into_inner(),
            }
        }
    }

    impl<'de, T: de::Deserialize<'de>> de::Deserialize<'de> for Spanned<T> {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: de::Deserializer<'de>,
        {
            Ok(if DISABLE_SPANNED_DESERIALIZATION.with(|d| d.get()) {
                T::deserialize(deserializer)?.into()
            } else {
                toml::Spanned::<T>::deserialize(deserializer)?.into()
            })
        }
    }

    impl<T: ser::Serialize> ser::Serialize for Spanned<T> {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: ser::Serializer,
        {
            self.value.serialize(serializer)
        }
    }
}

#[cfg(test)]
mod test {
    use crate::format::*;

    #[test]
    fn toml_formatter_wrapping() {
        let mut dc_long = SortedMap::new();
        dc_long.insert(
            "example-crate-1".to_owned().into(),
            vec![
                "criteria-one-very-long".to_owned().into(),
                "criteria-two-very-long".to_owned().into(),
            ],
        );
        dc_long.insert(
            "example-crate-2".to_owned().into(),
            vec![
                // This array would wrap over multiple lines if byte length was
                // used rather than utf-8 character length.
                "criteria-one-✨✨✨✨✨✨✨✨✨✨".to_owned().into(),
                "criteria-two-✨✨✨✨✨✨✨✨✨✨".to_owned().into(),
            ],
        );
        dc_long.insert(
            "example-crate-3".to_owned().into(),
            vec![
                "criteria-one-very-long".to_owned().into(),
                "criteria-two-very-long".to_owned().into(),
                "criteria-three-extremely-long-this-array-should-wrap"
                    .to_owned()
                    .into(),
            ],
        );

        let mut dc_short = SortedMap::new();
        dc_short.insert(
            "example-crate-1".to_owned().into(),
            vec!["criteria-one".to_owned().into()],
        );

        let mut policy = Policy::default();
        policy.insert(
            "long-criteria".to_owned(),
            PackagePolicyEntry::Unversioned(PolicyEntry {
                audit_as_crates_io: None,
                criteria: Some(vec!["long-criteria".to_owned().into()]),
                dev_criteria: None,
                dependency_criteria: dc_long,
                notes: Some("notes go here!".to_owned()),
            }),
        );
        policy.insert(
            "short-criteria".to_owned(),
            PackagePolicyEntry::Unversioned(PolicyEntry {
                audit_as_crates_io: None,
                criteria: Some(vec!["short-criteria".to_owned().into()]),
                dev_criteria: None,
                dependency_criteria: dc_short,
                notes: Some("notes go here!".to_owned()),
            }),
        );

        let formatted = super::to_formatted_toml(
            ConfigFile {
                cargo_vet: CargoVetConfig {
                    version: StoreVersion { major: 1, minor: 0 },
                },
                default_criteria: get_default_criteria(),
                imports: SortedMap::new(),
                policy,
                exemptions: SortedMap::new(),
            },
            None,
        )
        .unwrap()
        .to_string();

        insta::assert_snapshot!("formatted_toml_long_inline", formatted);
    }
}
