nvim-api 0.2.0

Neovim API bindings
Documentation
use std::fmt;

use nvim_types::{
    conversion::{self, ToObject},
    serde::Serializer,
    Object,
};
use serde::{de, ser, Serialize};

// use crate::object::{self, ToObject};

/// See `:h command-range` for details.
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum CommandRange {
    #[serde(serialize_with = "serialize_as_true")]
    CurrentLine,

    #[serde(rename = "%")]
    WholeFile,

    Count(u32),
}

impl ToObject for CommandRange {
    fn to_object(self) -> Result<Object, conversion::Error> {
        self.serialize(Serializer::new()).map_err(Into::into)
    }
}

impl<'de> de::Deserialize<'de> for CommandRange {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        struct CommandRangeVisitor;

        impl<'de> de::Visitor<'de> for CommandRangeVisitor {
            type Value = CommandRange;

            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str("\".\", \"%\" or an integer")
            }

            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                match v {
                    "." => return Ok(Self::Value::CurrentLine),
                    "%" => return Ok(Self::Value::WholeFile),

                    other => {
                        if let Ok(n) = other.parse::<u32>() {
                            return Ok(Self::Value::Count(n));
                        }
                    },
                };

                Err(E::invalid_value(
                    de::Unexpected::Str(v),
                    &"\".\", \"%\" or an integer",
                ))
            }
        }

        deserializer.deserialize_str(CommandRangeVisitor)
    }
}

fn serialize_as_true<S>(serializer: S) -> Result<S::Ok, S::Error>
where
    S: ser::Serializer,
{
    serializer.serialize_bool(true)
}