Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions nvpair/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ edition = "2018"
cstr-argument = "0.1"
nvpair-sys = { path = "../nvpair-sys", version = "0.4.0" }
foreign-types = "0.5.0"
serde = "1.0"

[badges]
travis-ci = { repository = "jmesmon/rust-libzfs" }
270 changes: 270 additions & 0 deletions nvpair/src/de.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
use crate::*;
use ::serde::de::{DeserializeSeed, MapAccess, SeqAccess, Visitor};
use ::serde::{de, forward_to_deserialize_any, Deserialize};
use serde::de::DeserializeOwned;
use std::ffi::CStr;
use std::marker::PhantomData;

pub fn from_bytes<T>(buf: &[u8]) -> Result<T>
where
T: DeserializeOwned,
{
from_nvlist(&NvList::try_unpack(buf)?)
}

pub fn from_nvlist<'a, T>(s: &'a NvList) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::from_nvlist(s);
let t = T::deserialize(&mut deserializer)?;
/*
match deserializer.iterator.next() {
Some(pair) => Err(Error::Message(format!(
"unconsumed nvpairs, including {:?}",
pair
))),
None => Ok(t),
}
*/
Ok(t)
}

#[derive(Debug)]
struct Deserializer<'de> {
iterator: NvListIter<'de>,
data: Option<NvData<'de>>,
}

impl<'de> Deserializer<'de> {
fn from_nvlist(input: &'de NvListRef) -> Self {
Deserializer {
iterator: input.iter(),
data: None,
}
}
}

impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_map(self)
}

forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}

impl<'de> MapAccess<'de> for Deserializer<'de> {
type Error = Error;

fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
let nvpair = match self.iterator.next() {
Some(nvpair) => nvpair,
None => return Ok(None),
};

let mut key_deserializer = KeyDeserializer { key: nvpair.name() };
self.data = Some(nvpair.data());

seed.deserialize(&mut key_deserializer).map(Some)
}

fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
match self.data.take() {
Some(data) => {
let mut value_deserializer = ValueDeserializer { data };
seed.deserialize(&mut value_deserializer)
}
None => Err(Error::Message("expected value but not present".to_string())),
}
}
}

#[derive(Debug)]
struct KeyDeserializer<'de> {
key: &'de CStr,
}

impl<'de, 'a> de::Deserializer<'de> for &'a mut KeyDeserializer<'de> {
type Error = Error;

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_borrowed_str(self.key.to_str()?)
}

forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}

#[derive(Debug)]
struct ValueDeserializer<'de> {
data: NvData<'de>,
}

impl<'de, 'a> de::Deserializer<'de> for &'a mut ValueDeserializer<'de> {
type Error = Error;

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self.data {
NvData::Unknown => Err(Error::UnknownNvPairType),
NvData::Bool => visitor.visit_none(),
NvData::BoolV(v) => visitor.visit_bool(v),
NvData::Byte(v) => visitor.visit_u8(v),
NvData::Int8(v) => visitor.visit_i8(v),
NvData::Uint8(v) => visitor.visit_u8(v),
NvData::Int16(v) => visitor.visit_i16(v),
NvData::Uint16(v) => visitor.visit_u16(v),
NvData::Int32(v) => visitor.visit_i32(v),
NvData::Uint32(v) => visitor.visit_u32(v),
NvData::Int64(v) => visitor.visit_i64(v),
NvData::Uint64(v) => visitor.visit_u64(v),
NvData::Str(v) => visitor.visit_borrowed_str(v.to_str()?),
NvData::NvListRef(v) => visitor.visit_map(Deserializer::from_nvlist(v)),
NvData::ByteArray(v) => visitor.visit_borrowed_bytes(v),
NvData::Int8Array(v) => visitor.visit_seq(SeqAccessor::new(v.iter())),
NvData::Uint8Array(v) => visitor.visit_borrowed_bytes(v),
NvData::Int16Array(v) => visitor.visit_seq(SeqAccessor::new(v.iter())),
NvData::Uint16Array(v) => visitor.visit_seq(SeqAccessor::new(v.iter())),
NvData::Int32Array(v) => visitor.visit_seq(SeqAccessor::new(v.iter())),
NvData::Uint32Array(v) => visitor.visit_seq(SeqAccessor::new(v.iter())),
NvData::Int64Array(v) => visitor.visit_seq(SeqAccessor::new(v.iter())),
NvData::Uint64Array(v) => visitor.visit_seq(SeqAccessor::new(v.iter())),
NvData::NvListRefArray(_) => Err(Error::UnknownNvPairType),
}
}

forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}

#[derive(Debug)]
struct SeqAccessor<'de, I>
where
I: Iterator,
<I as Iterator>::Item: Into<NvData<'de>>,
{
iterator: I,
_phantom: std::marker::PhantomData<&'de I>,
}

impl<'de, I> SeqAccessor<'de, I>
where
I: Iterator,
<I as Iterator>::Item: Into<NvData<'de>>,
{
fn new(iterator: I) -> Self {
Self {
iterator,
_phantom: PhantomData,
}
}
}

impl<'de, I> SeqAccess<'de> for SeqAccessor<'de, I>
where
I: Iterator,
<I as Iterator>::Item: Into<NvData<'de>>,
{
type Error = Error;

fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
let item = match self.iterator.next() {
Some(item) => item,
None => return Ok(None),
};

let mut vd = ValueDeserializer { data: item.into() };
seed.deserialize(&mut vd).map(Some)
}
}

impl From<&u64> for NvData<'_> {
fn from(v: &u64) -> Self {
NvData::Uint64(*v)
}
}

impl From<&i64> for NvData<'_> {
fn from(v: &i64) -> Self {
NvData::Int64(*v)
}
}

impl From<&u32> for NvData<'_> {
fn from(v: &u32) -> Self {
NvData::Uint32(*v)
}
}

impl From<&i32> for NvData<'_> {
fn from(v: &i32) -> Self {
NvData::Int32(*v)
}
}

impl From<&u16> for NvData<'_> {
fn from(v: &u16) -> Self {
NvData::Uint16(*v)
}
}

impl From<&i16> for NvData<'_> {
fn from(v: &i16) -> Self {
NvData::Int16(*v)
}
}

impl From<&u8> for NvData<'_> {
fn from(v: &u8) -> Self {
NvData::Uint8(*v)
}
}

impl From<&i8> for NvData<'_> {
fn from(v: &i8) -> Self {
NvData::Int8(*v)
}
}

/*
impl<'a> From<&'a NvListRef> for NvData<'a> {
fn from(v: &'a NvListRef) -> Self {
NvData::NvListRef(v)
}
}

impl<'a> From<&&'a NvListRef> for NvData<'a> {
fn from(v: &&'a NvListRef) -> Self {
NvData::NvListRef(*v)
}
}
*/
74 changes: 74 additions & 0 deletions nvpair/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use ::serde::{de, ser};
use std::ffi::NulError;
use std::fmt;
use std::fmt::Display;

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
Message(String),
UnknownNvPairType,

// Zero or more variants that can be created directly by the Serializer and
// Deserializer without going through `ser::Error` and `de::Error`. These
// are specific to the format, in this case JSON.
//Eof,
NulError(NulError),
IoError(std::io::Error),
Utf8Error(std::str::Utf8Error),
/*
Syntax,
ExpectedBoolean,
ExpectedInteger,
ExpectedString,
ExpectedNull,
ExpectedArray,
ExpectedArrayComma,
ExpectedArrayEnd,
ExpectedMap,
ExpectedMapColon,
ExpectedMapComma,
ExpectedMapEnd,
ExpectedEnum,
TrailingCharacters,
*/
}

impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error::Message(msg.to_string())
}
}

impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error::Message(msg.to_string())
}
}

impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, formatter)
}
}

impl From<NulError> for Error {
fn from(e: NulError) -> Self {
Error::NulError(e)
}
}

impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::IoError(e)
}
}

impl From<std::str::Utf8Error> for Error {
fn from(e: std::str::Utf8Error) -> Self {
Error::Utf8Error(e)
}
}

impl std::error::Error for Error {}
Loading