<commit_before>// Copyright 2015, Igor Shaula
// Licensed under the MIT License <LICENSE or
// http://opensource.org/licenses/MIT>. This file
// may not be copied, modified, or distributed
// except according to those terms.

//! Traits for loading/saving Registry values
use std::slice;
use std::io;
use super::winapi::winerror;
use super::{RegValue};
use super::enums::*;
use super::{to_utf16,v16_to_v8};

/// A trait for types that can be loaded from registry values.
pub trait FromRegValue : Sized {
    fn from_reg_value(val: &RegValue) -> io::Result<Self>;
}

impl FromRegValue for String {
    fn from_reg_value(val: &RegValue) -> io::Result<String> {
        match val.vtype {
            REG_SZ | REG_EXPAND_SZ | REG_MULTI_SZ => {
                let words = unsafe {
                    slice::from_raw_parts(val.bytes.as_ptr() as *const u16, val.bytes.len() / 2)
                };
                let mut s = String::from_utf16_lossy(words);
                while s.ends_with("\u{0}") {s.pop();}
                if val.vtype == REG_MULTI_SZ {
                    return Ok(s.replace("\u{0}", "\n"))
                }
                Ok(s)
            },
            _ => werr!(winerror::ERROR_BAD_FILE_TYPE)
        }
    }
}

impl FromRegValue for u32 {
    fn from_reg_value(val: &RegValue) -> io::Result<u32> {
        match val.vtype {
            REG_DWORD => {
                Ok(unsafe{ *(val.bytes.as_ptr() as *const u32) })
            },
            _ => werr!(winerror::ERROR_BAD_FILE_TYPE)
        }
    }
}

impl FromRegValue for u64 {
    fn from_reg_value(val: &RegValue) -> io::Result<u64> {
        match val.vtype {
            REG_QWORD => {
                Ok(unsafe{ *(val.bytes.as_ptr() as *const u64) })
            },
            _ => werr!(winerror::ERROR_BAD_FILE_TYPE)
        }
    }
}

/// A trait for types that can be written into registry values.
pub trait ToRegValue {
    fn to_reg_value(&self) -> RegValue;
}

impl ToRegValue for String {
    fn to_reg_value(&self) -> RegValue {
        RegValue{
            bytes: v16_to_v8(&to_utf16(self)),
            vtype: REG_SZ
        }
    }
}

impl<'a> ToRegValue for &'a str {
    fn to_reg_value(&self) -> RegValue {
        RegValue{
            bytes: v16_to_v8(&to_utf16(self)),
            vtype: REG_SZ
        }
    }
}

impl ToRegValue for u32 {
    fn to_reg_value(&self) -> RegValue {
        let bytes: Vec<u8> = unsafe {
            slice::from_raw_parts((self as *const u32) as *const u8, 4).to_vec()
        };
        RegValue{
            bytes: bytes,
            vtype: REG_DWORD
        }
    }
}

impl ToRegValue for u64 {
    fn to_reg_value(&self) -> RegValue {
        let bytes: Vec<u8> = unsafe {
            slice::from_raw_parts((self as *const u64) as *const u8, 8).to_vec()
        };
        RegValue{
            bytes: bytes,
            vtype: REG_QWORD
        }
    }
}
<commit_msg>Fix clippy single_char_pattern warning<commit_after>// Copyright 2015, Igor Shaula
// Licensed under the MIT License <LICENSE or
// http://opensource.org/licenses/MIT>. This file
// may not be copied, modified, or distributed
// except according to those terms.

//! Traits for loading/saving Registry values
use std::slice;
use std::io;
use super::winapi::winerror;
use super::{RegValue};
use super::enums::*;
use super::{to_utf16,v16_to_v8};

/// A trait for types that can be loaded from registry values.
pub trait FromRegValue : Sized {
    fn from_reg_value(val: &RegValue) -> io::Result<Self>;
}

impl FromRegValue for String {
    fn from_reg_value(val: &RegValue) -> io::Result<String> {
        match val.vtype {
            REG_SZ | REG_EXPAND_SZ | REG_MULTI_SZ => {
                let words = unsafe {
                    slice::from_raw_parts(val.bytes.as_ptr() as *const u16, val.bytes.len() / 2)
                };
                let mut s = String::from_utf16_lossy(words);
                while s.ends_with('\u{0}') {s.pop();}
                if val.vtype == REG_MULTI_SZ {
                    return Ok(s.replace("\u{0}", "\n"))
                }
                Ok(s)
            },
            _ => werr!(winerror::ERROR_BAD_FILE_TYPE)
        }
    }
}

impl FromRegValue for u32 {
    fn from_reg_value(val: &RegValue) -> io::Result<u32> {
        match val.vtype {
            REG_DWORD => {
                Ok(unsafe{ *(val.bytes.as_ptr() as *const u32) })
            },
            _ => werr!(winerror::ERROR_BAD_FILE_TYPE)
        }
    }
}

impl FromRegValue for u64 {
    fn from_reg_value(val: &RegValue) -> io::Result<u64> {
        match val.vtype {
            REG_QWORD => {
                Ok(unsafe{ *(val.bytes.as_ptr() as *const u64) })
            },
            _ => werr!(winerror::ERROR_BAD_FILE_TYPE)
        }
    }
}

/// A trait for types that can be written into registry values.
pub trait ToRegValue {
    fn to_reg_value(&self) -> RegValue;
}

impl ToRegValue for String {
    fn to_reg_value(&self) -> RegValue {
        RegValue{
            bytes: v16_to_v8(&to_utf16(self)),
            vtype: REG_SZ
        }
    }
}

impl<'a> ToRegValue for &'a str {
    fn to_reg_value(&self) -> RegValue {
        RegValue{
            bytes: v16_to_v8(&to_utf16(self)),
            vtype: REG_SZ
        }
    }
}

impl ToRegValue for u32 {
    fn to_reg_value(&self) -> RegValue {
        let bytes: Vec<u8> = unsafe {
            slice::from_raw_parts((self as *const u32) as *const u8, 4).to_vec()
        };
        RegValue{
            bytes: bytes,
            vtype: REG_DWORD
        }
    }
}

impl ToRegValue for u64 {
    fn to_reg_value(&self) -> RegValue {
        let bytes: Vec<u8> = unsafe {
            slice::from_raw_parts((self as *const u64) as *const u8, 8).to_vec()
        };
        RegValue{
            bytes: bytes,
            vtype: REG_QWORD
        }
    }
}
<|endoftext|>


<commit_before>use std::{mem};

use num::{BigInt, One, Signed};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BitString {
    data: Vec<u8>,
    bit_length: usize,
}

impl BitString {
    pub fn from_bytes(data: Vec<u8>) -> Option<BitString> {
        let length = data.len() * 8;
        return BitString::new(data, length);
    }

    pub fn new(data: Vec<u8>, bit_length: usize) -> Option<BitString> {
        match (data.len(), bit_length) {
            (0, 0) => (),
            (_, 0) | (0, _) => return None,
            (i, j) if (i * 8 < j) || (i - 1) * 8 > j => return None,
            _ => (),
        }

        let padding_bits = data.len() * 8 - bit_length;
        if padding_bits > 0 && data[data.len() - 1] & ((1 << padding_bits) - 1) != 0 {
            return None;
        }

        return Some(BitString {
            data: data,
            bit_length: bit_length,
        });
    }

    pub fn len(&self) -> usize {
        return self.bit_length;
    }

    pub fn as_bytes(&self) -> &Vec<u8> {
        return &self.data;
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer: Sized {
    fn encode(&self) -> Vec<u8>;
    fn decode(&[u8]) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: &[u8]) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                } else if data.is_empty() {
                    return Err(DeserializationError::InvalidValue);
                }

                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        if self.is_positive() {
            let (_, mut bytes) = self.to_bytes_be();
            if bytes[0] & 0x80 == 0x80 {
                // If the data has a leading 0x80, pad with a zero-byte.
                bytes.insert(0, 0);
            }
            return bytes;
        } else if self.is_negative() {
            // Convert negative numbers to two's-complement by subtracting one and inverting.
            let n_minus_1 = -self - BigInt::one();
            let (_, mut bytes) = n_minus_1.to_bytes_be();

            for i in 0..bytes.len() {
                bytes[i] ^= 0xff;
            }

            if bytes[0] & 0x80 == 0 {
                bytes.insert(0, 0xff);
            }
            return bytes;
        } else {
            return b"\x00".to_vec();
        }
    }

    fn decode(data: &[u8]) -> DeserializationResult<BigInt> {
        if data.is_empty() {
            return Err(DeserializationError::InvalidValue);
        }

        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{BitString, ObjectIdentifier};

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }

    #[test]
    fn test_bit_string_new() {
        assert!(BitString::new(b"".to_vec(), 1).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 0).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 9).is_none());
        assert!(BitString::new(b"\xff".to_vec(), 3).is_none());
    }

    #[test]
    fn test_bit_string_from_bytes() {
        assert_eq!(BitString::from_bytes(b"".to_vec()), BitString::new(b"".to_vec(), 0));
        assert_eq!(BitString::from_bytes(b"abc".to_vec()), BitString::new(b"abc".to_vec(), 24));
    }
}
<commit_msg>Use more correct return type for as_bytes<commit_after>use std::{mem};

use num::{BigInt, One, Signed};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BitString {
    data: Vec<u8>,
    bit_length: usize,
}

impl BitString {
    pub fn from_bytes(data: Vec<u8>) -> Option<BitString> {
        let length = data.len() * 8;
        return BitString::new(data, length);
    }

    pub fn new(data: Vec<u8>, bit_length: usize) -> Option<BitString> {
        match (data.len(), bit_length) {
            (0, 0) => (),
            (_, 0) | (0, _) => return None,
            (i, j) if (i * 8 < j) || (i - 1) * 8 > j => return None,
            _ => (),
        }

        let padding_bits = data.len() * 8 - bit_length;
        if padding_bits > 0 && data[data.len() - 1] & ((1 << padding_bits) - 1) != 0 {
            return None;
        }

        return Some(BitString {
            data: data,
            bit_length: bit_length,
        });
    }

    pub fn len(&self) -> usize {
        return self.bit_length;
    }

    pub fn as_bytes(&self) -> &[u8] {
        return &self.data;
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer: Sized {
    fn encode(&self) -> Vec<u8>;
    fn decode(&[u8]) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: &[u8]) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                } else if data.is_empty() {
                    return Err(DeserializationError::InvalidValue);
                }

                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        if self.is_positive() {
            let (_, mut bytes) = self.to_bytes_be();
            if bytes[0] & 0x80 == 0x80 {
                // If the data has a leading 0x80, pad with a zero-byte.
                bytes.insert(0, 0);
            }
            return bytes;
        } else if self.is_negative() {
            // Convert negative numbers to two's-complement by subtracting one and inverting.
            let n_minus_1 = -self - BigInt::one();
            let (_, mut bytes) = n_minus_1.to_bytes_be();

            for i in 0..bytes.len() {
                bytes[i] ^= 0xff;
            }

            if bytes[0] & 0x80 == 0 {
                bytes.insert(0, 0xff);
            }
            return bytes;
        } else {
            return b"\x00".to_vec();
        }
    }

    fn decode(data: &[u8]) -> DeserializationResult<BigInt> {
        if data.is_empty() {
            return Err(DeserializationError::InvalidValue);
        }

        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{BitString, ObjectIdentifier};

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }

    #[test]
    fn test_bit_string_new() {
        assert!(BitString::new(b"".to_vec(), 1).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 0).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 9).is_none());
        assert!(BitString::new(b"\xff".to_vec(), 3).is_none());
    }

    #[test]
    fn test_bit_string_from_bytes() {
        assert_eq!(BitString::from_bytes(b"".to_vec()), BitString::new(b"".to_vec(), 0));
        assert_eq!(BitString::from_bytes(b"abc".to_vec()), BitString::new(b"abc".to_vec(), 24));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::cmp::Ordering;

use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMetaItem,
                  NestedMetaItemKind, Path};
use syntax::codemap::{BytePos, Span, NO_EXPANSION};
use syntax::abi;

use Shape;
use rewrite::{Rewrite, RewriteContext};

use SKIP_ANNOTATION;

// Computes the length of a string's last line, minus offset.
pub fn extra_offset(text: &str, shape: Shape) -> usize {
    match text.rfind('\n') {
        // 1 for newline character
        Some(idx) => {
            text.len()
                .checked_sub(idx + 1 + shape.used_width())
                .unwrap_or(0)
        }
        None => text.len(),
    }
}

// Uses Cow to avoid allocating in the common cases.
pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> {
    match *vis {
        Visibility::Public => Cow::from("pub "),
        Visibility::Inherited => Cow::from(""),
        Visibility::Crate(_) => Cow::from("pub(crate) "),
        Visibility::Restricted { ref path, .. } => {
            let Path { ref segments, .. } = **path;
            let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string());
            if path.is_global() {
                segments_iter
                    .next()
                    .expect("Non-global path in pub(restricted)?");
            }

            Cow::from(format!("pub({}) ", segments_iter.collect::<Vec<_>>().join("::")))
        }
    }
}

#[inline]
pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str {
    match unsafety {
        ast::Unsafety::Unsafe => "unsafe ",
        ast::Unsafety::Normal => "",
    }
}

#[inline]
pub fn format_mutability(mutability: ast::Mutability) -> &'static str {
    match mutability {
        ast::Mutability::Mutable => "mut ",
        ast::Mutability::Immutable => "",
    }
}

#[inline]
pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> String {
    if abi == abi::Abi::C && !explicit_abi {
        "extern ".into()
    } else {
        format!("extern {} ", abi)
    }
}

// The width of the first line in s.
#[inline]
pub fn first_line_width(s: &str) -> usize {
    match s.find('\n') {
        Some(n) => n,
        None => s.len(),
    }
}

// The width of the last line in s.
#[inline]
pub fn last_line_width(s: &str) -> usize {
    match s.rfind('\n') {
        Some(n) => s.len() - n - 1,
        None => s.len(),
    }
}
#[inline]
pub fn trimmed_last_line_width(s: &str) -> usize {
    match s.rfind('\n') {
        Some(n) => s[(n + 1)..].trim().len(),
        None => s.trim().len(),
    }
}

#[inline]
fn is_skip(meta_item: &MetaItem) -> bool {
    match meta_item.node {
        MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION,
        MetaItemKind::List(ref l) => {
            meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1])
        }
        _ => false,
    }
}

#[inline]
fn is_skip_nested(meta_item: &NestedMetaItem) -> bool {
    match meta_item.node {
        NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi),
        NestedMetaItemKind::Literal(_) => false,
    }
}

#[inline]
pub fn contains_skip(attrs: &[Attribute]) -> bool {
    attrs
        .iter()
        .any(|a| a.meta().map_or(false, |a| is_skip(&a)))
}

// Find the end of a TyParam
#[inline]
pub fn end_typaram(typaram: &ast::TyParam) -> BytePos {
    typaram
        .bounds
        .last()
        .map_or(typaram.span, |bound| match *bound {
            ast::RegionTyParamBound(ref lt) => lt.span,
            ast::TraitTyParamBound(ref prt, _) => prt.span,
        })
        .hi
}

#[inline]
pub fn semicolon_for_expr(expr: &ast::Expr) -> bool {
    match expr.node {
        ast::ExprKind::Ret(..) |
        ast::ExprKind::Continue(..) |
        ast::ExprKind::Break(..) => true,
        _ => false,
    }
}

#[inline]
pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool {
    match stmt.node {
        ast::StmtKind::Semi(ref expr) => {
            match expr.node {
                ast::ExprKind::While(..) |
                ast::ExprKind::WhileLet(..) |
                ast::ExprKind::Loop(..) |
                ast::ExprKind::ForLoop(..) => false,
                _ => true,
            }
        }
        ast::StmtKind::Expr(..) => false,
        _ => true,
    }
}

#[inline]
pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> {
    match stmt.node {
        ast::StmtKind::Expr(ref expr) => Some(expr),
        _ => None,
    }
}

#[inline]
pub fn trim_newlines(input: &str) -> &str {
    match input.find(|c| c != '\n' && c != '\r') {
        Some(start) => {
            let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1;
            &input[start..end]
        }
        None => "",
    }
}

// Macro for deriving implementations of Serialize/Deserialize for enums
#[macro_export]
macro_rules! impl_enum_serialize_and_deserialize {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::serde::ser::Serialize for $e {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: ::serde::ser::Serializer
            {
                use serde::ser::Error;

                // We don't know whether the user of the macro has given us all options.
                #[allow(unreachable_patterns)]
                match *self {
                    $(
                        $e::$x => serializer.serialize_str(stringify!($x)),
                    )*
                    _ => {
                        Err(S::Error::custom(format!("Cannot serialize {:?}", self)))
                    }
                }
            }
        }

        impl<'de> ::serde::de::Deserialize<'de> for $e {
            fn deserialize<D>(d: D) -> Result<Self, D::Error>
                    where D: ::serde::Deserializer<'de> {
                use std::ascii::AsciiExt;
                use serde::de::{Error, Visitor};
                use std::marker::PhantomData;
                use std::fmt;
                struct StringOnly<T>(PhantomData<T>);
                impl<'de, T> Visitor<'de> for StringOnly<T>
                        where T: ::serde::Deserializer<'de> {
                    type Value = String;
                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("string")
                    }
                    fn visit_str<E>(self, value: &str) -> Result<String, E> {
                        Ok(String::from(value))
                    }
                }
                let s = d.deserialize_string(StringOnly::<D>(PhantomData))?;
                $(
                    if stringify!($x).eq_ignore_ascii_case(&s) {
                      return Ok($e::$x);
                    }
                )*
                static ALLOWED: &'static[&str] = &[$(stringify!($x),)*];
                Err(D::Error::unknown_variant(&s, ALLOWED))
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                use std::ascii::AsciiExt;
                $(
                    if stringify!($x).eq_ignore_ascii_case(s) {
                        return Ok($e::$x);
                    }
                )*
                Err("Bad variant")
            }
        }

        impl ::config::ConfigType for $e {
            fn doc_hint() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

// Same as try!, but for Option
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => (match $expr {
        Some(val) => val,
        None => { return None; }
    })
}

macro_rules! msg {
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
}

// For format_missing and last_pos, need to use the source callsite (if applicable).
// Required as generated code spans aren't guaranteed to follow on from the last span.
macro_rules! source {
    ($this:ident, $sp: expr) => {
        $sp.source_callsite()
    }
}

pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
    Span {
        lo,
        hi,
        ctxt: NO_EXPANSION,
    }
}

// Wraps string-like values in an Option. Returns Some when the string adheres
// to the Rewrite constraints defined for the Rewrite trait and else otherwise.
pub fn wrap_str<S: AsRef<str>>(s: S, max_width: usize, shape: Shape) -> Option<S> {
    {
        let snippet = s.as_ref();

        if !snippet.is_empty() {
            if !snippet.contains('\n') && snippet.len() > shape.width {
                return None;
            } else {
                let mut lines = snippet.lines();

                // The caller of this function has already placed `shape.offset`
                // characters on the first line.
                let first_line_max_len = try_opt!(max_width.checked_sub(shape.indent.width()));
                if lines.next().unwrap().len() > first_line_max_len {
                    return None;
                }

                // The other lines must fit within the maximum width.
                if lines.any(|line| line.len() > max_width) {
                    return None;
                }

                // `width` is the maximum length of the last line, excluding
                // indentation.
                // A special check for the last line, since the caller may
                // place trailing characters on this line.
                if snippet.lines().rev().next().unwrap().len() >
                   shape.indent.width() + shape.width {
                    return None;
                }
            }
        }
    }

    Some(s)
}

impl Rewrite for String {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        wrap_str(self, context.config.max_width(), shape).map(ToOwned::to_owned)
    }
}

// Binary search in integer range. Returns the first Ok value returned by the
// callback.
// The callback takes an integer and returns either an Ok, or an Err indicating
// whether the `guess' was too high (Ordering::Less), or too low.
// This function is guaranteed to try to the hi value first.
pub fn binary_search<C, T>(mut lo: usize, mut hi: usize, callback: C) -> Option<T>
    where C: Fn(usize) -> Result<T, Ordering>
{
    let mut middle = hi;

    while lo <= hi {
        match callback(middle) {
            Ok(val) => return Some(val),
            Err(Ordering::Less) => {
                hi = middle - 1;
            }
            Err(..) => {
                lo = middle + 1;
            }
        }
        middle = (hi + lo) / 2;
    }

    None
}

#[inline]
pub fn colon_spaces(before: bool, after: bool) -> &'static str {
    match (before, after) {
        (true, true) => " : ",
        (true, false) => " :",
        (false, true) => ": ",
        (false, false) => ":",
    }
}

#[test]
fn bin_search_test() {
    let closure = |i| match i {
        4 => Ok(()),
        j if j > 4 => Err(Ordering::Less),
        j if j < 4 => Err(Ordering::Greater),
        _ => unreachable!(),
    };

    assert_eq!(Some(()), binary_search(1, 10, &closure));
    assert_eq!(None, binary_search(1, 3, &closure));
    assert_eq!(Some(()), binary_search(0, 44, &closure));
    assert_eq!(Some(()), binary_search(4, 125, &closure));
    assert_eq!(None, binary_search(6, 100, &closure));
}

pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr {
    match e.node {
        ast::ExprKind::InPlace(ref e, _) |
        ast::ExprKind::Call(ref e, _) |
        ast::ExprKind::Binary(_, ref e, _) |
        ast::ExprKind::Cast(ref e, _) |
        ast::ExprKind::Type(ref e, _) |
        ast::ExprKind::Assign(ref e, _) |
        ast::ExprKind::AssignOp(_, ref e, _) |
        ast::ExprKind::Field(ref e, _) |
        ast::ExprKind::TupField(ref e, _) |
        ast::ExprKind::Index(ref e, _) |
        ast::ExprKind::Range(Some(ref e), _, _) |
        ast::ExprKind::Try(ref e) => left_most_sub_expr(e),
        _ => e,
    }
}
<commit_msg>Format pub(restricted) properly<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::cmp::Ordering;

use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMetaItem,
                  NestedMetaItemKind, Path};
use syntax::codemap::{BytePos, Span, NO_EXPANSION};
use syntax::abi;

use Shape;
use rewrite::{Rewrite, RewriteContext};

use SKIP_ANNOTATION;

// Computes the length of a string's last line, minus offset.
pub fn extra_offset(text: &str, shape: Shape) -> usize {
    match text.rfind('\n') {
        // 1 for newline character
        Some(idx) => {
            text.len()
                .checked_sub(idx + 1 + shape.used_width())
                .unwrap_or(0)
        }
        None => text.len(),
    }
}

// Uses Cow to avoid allocating in the common cases.
pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> {
    match *vis {
        Visibility::Public => Cow::from("pub "),
        Visibility::Inherited => Cow::from(""),
        Visibility::Crate(_) => Cow::from("pub(crate) "),
        Visibility::Restricted { ref path, .. } => {
            let Path { ref segments, .. } = **path;
            let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string());
            if path.is_global() {
                segments_iter
                    .next()
                    .expect("Non-global path in pub(restricted)?");
            }
            let is_keyword = |s: &str| s == "self" || s == "super";
            let path = segments_iter.join("::");
            let in_str = if is_keyword(&path) { "" } else { "in " };

            Cow::from(format!("pub({}{}) ", in_str, path))
        }
    }
}

#[inline]
pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str {
    match unsafety {
        ast::Unsafety::Unsafe => "unsafe ",
        ast::Unsafety::Normal => "",
    }
}

#[inline]
pub fn format_mutability(mutability: ast::Mutability) -> &'static str {
    match mutability {
        ast::Mutability::Mutable => "mut ",
        ast::Mutability::Immutable => "",
    }
}

#[inline]
pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> String {
    if abi == abi::Abi::C && !explicit_abi {
        "extern ".into()
    } else {
        format!("extern {} ", abi)
    }
}

// The width of the first line in s.
#[inline]
pub fn first_line_width(s: &str) -> usize {
    match s.find('\n') {
        Some(n) => n,
        None => s.len(),
    }
}

// The width of the last line in s.
#[inline]
pub fn last_line_width(s: &str) -> usize {
    match s.rfind('\n') {
        Some(n) => s.len() - n - 1,
        None => s.len(),
    }
}
#[inline]
pub fn trimmed_last_line_width(s: &str) -> usize {
    match s.rfind('\n') {
        Some(n) => s[(n + 1)..].trim().len(),
        None => s.trim().len(),
    }
}

#[inline]
fn is_skip(meta_item: &MetaItem) -> bool {
    match meta_item.node {
        MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION,
        MetaItemKind::List(ref l) => {
            meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1])
        }
        _ => false,
    }
}

#[inline]
fn is_skip_nested(meta_item: &NestedMetaItem) -> bool {
    match meta_item.node {
        NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi),
        NestedMetaItemKind::Literal(_) => false,
    }
}

#[inline]
pub fn contains_skip(attrs: &[Attribute]) -> bool {
    attrs
        .iter()
        .any(|a| a.meta().map_or(false, |a| is_skip(&a)))
}

// Find the end of a TyParam
#[inline]
pub fn end_typaram(typaram: &ast::TyParam) -> BytePos {
    typaram
        .bounds
        .last()
        .map_or(typaram.span, |bound| match *bound {
            ast::RegionTyParamBound(ref lt) => lt.span,
            ast::TraitTyParamBound(ref prt, _) => prt.span,
        })
        .hi
}

#[inline]
pub fn semicolon_for_expr(expr: &ast::Expr) -> bool {
    match expr.node {
        ast::ExprKind::Ret(..) |
        ast::ExprKind::Continue(..) |
        ast::ExprKind::Break(..) => true,
        _ => false,
    }
}

#[inline]
pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool {
    match stmt.node {
        ast::StmtKind::Semi(ref expr) => {
            match expr.node {
                ast::ExprKind::While(..) |
                ast::ExprKind::WhileLet(..) |
                ast::ExprKind::Loop(..) |
                ast::ExprKind::ForLoop(..) => false,
                _ => true,
            }
        }
        ast::StmtKind::Expr(..) => false,
        _ => true,
    }
}

#[inline]
pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> {
    match stmt.node {
        ast::StmtKind::Expr(ref expr) => Some(expr),
        _ => None,
    }
}

#[inline]
pub fn trim_newlines(input: &str) -> &str {
    match input.find(|c| c != '\n' && c != '\r') {
        Some(start) => {
            let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1;
            &input[start..end]
        }
        None => "",
    }
}

// Macro for deriving implementations of Serialize/Deserialize for enums
#[macro_export]
macro_rules! impl_enum_serialize_and_deserialize {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::serde::ser::Serialize for $e {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: ::serde::ser::Serializer
            {
                use serde::ser::Error;

                // We don't know whether the user of the macro has given us all options.
                #[allow(unreachable_patterns)]
                match *self {
                    $(
                        $e::$x => serializer.serialize_str(stringify!($x)),
                    )*
                    _ => {
                        Err(S::Error::custom(format!("Cannot serialize {:?}", self)))
                    }
                }
            }
        }

        impl<'de> ::serde::de::Deserialize<'de> for $e {
            fn deserialize<D>(d: D) -> Result<Self, D::Error>
                    where D: ::serde::Deserializer<'de> {
                use std::ascii::AsciiExt;
                use serde::de::{Error, Visitor};
                use std::marker::PhantomData;
                use std::fmt;
                struct StringOnly<T>(PhantomData<T>);
                impl<'de, T> Visitor<'de> for StringOnly<T>
                        where T: ::serde::Deserializer<'de> {
                    type Value = String;
                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("string")
                    }
                    fn visit_str<E>(self, value: &str) -> Result<String, E> {
                        Ok(String::from(value))
                    }
                }
                let s = d.deserialize_string(StringOnly::<D>(PhantomData))?;
                $(
                    if stringify!($x).eq_ignore_ascii_case(&s) {
                      return Ok($e::$x);
                    }
                )*
                static ALLOWED: &'static[&str] = &[$(stringify!($x),)*];
                Err(D::Error::unknown_variant(&s, ALLOWED))
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                use std::ascii::AsciiExt;
                $(
                    if stringify!($x).eq_ignore_ascii_case(s) {
                        return Ok($e::$x);
                    }
                )*
                Err("Bad variant")
            }
        }

        impl ::config::ConfigType for $e {
            fn doc_hint() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

// Same as try!, but for Option
#[macro_export]
macro_rules! try_opt {
    ($expr:expr) => (match $expr {
        Some(val) => val,
        None => { return None; }
    })
}

macro_rules! msg {
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr: {}", x),
        }
    )
}

// For format_missing and last_pos, need to use the source callsite (if applicable).
// Required as generated code spans aren't guaranteed to follow on from the last span.
macro_rules! source {
    ($this:ident, $sp: expr) => {
        $sp.source_callsite()
    }
}

pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
    Span {
        lo,
        hi,
        ctxt: NO_EXPANSION,
    }
}

// Wraps string-like values in an Option. Returns Some when the string adheres
// to the Rewrite constraints defined for the Rewrite trait and else otherwise.
pub fn wrap_str<S: AsRef<str>>(s: S, max_width: usize, shape: Shape) -> Option<S> {
    {
        let snippet = s.as_ref();

        if !snippet.is_empty() {
            if !snippet.contains('\n') && snippet.len() > shape.width {
                return None;
            } else {
                let mut lines = snippet.lines();

                // The caller of this function has already placed `shape.offset`
                // characters on the first line.
                let first_line_max_len = try_opt!(max_width.checked_sub(shape.indent.width()));
                if lines.next().unwrap().len() > first_line_max_len {
                    return None;
                }

                // The other lines must fit within the maximum width.
                if lines.any(|line| line.len() > max_width) {
                    return None;
                }

                // `width` is the maximum length of the last line, excluding
                // indentation.
                // A special check for the last line, since the caller may
                // place trailing characters on this line.
                if snippet.lines().rev().next().unwrap().len() >
                   shape.indent.width() + shape.width {
                    return None;
                }
            }
        }
    }

    Some(s)
}

impl Rewrite for String {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        wrap_str(self, context.config.max_width(), shape).map(ToOwned::to_owned)
    }
}

// Binary search in integer range. Returns the first Ok value returned by the
// callback.
// The callback takes an integer and returns either an Ok, or an Err indicating
// whether the `guess' was too high (Ordering::Less), or too low.
// This function is guaranteed to try to the hi value first.
pub fn binary_search<C, T>(mut lo: usize, mut hi: usize, callback: C) -> Option<T>
    where C: Fn(usize) -> Result<T, Ordering>
{
    let mut middle = hi;

    while lo <= hi {
        match callback(middle) {
            Ok(val) => return Some(val),
            Err(Ordering::Less) => {
                hi = middle - 1;
            }
            Err(..) => {
                lo = middle + 1;
            }
        }
        middle = (hi + lo) / 2;
    }

    None
}

#[inline]
pub fn colon_spaces(before: bool, after: bool) -> &'static str {
    match (before, after) {
        (true, true) => " : ",
        (true, false) => " :",
        (false, true) => ": ",
        (false, false) => ":",
    }
}

#[test]
fn bin_search_test() {
    let closure = |i| match i {
        4 => Ok(()),
        j if j > 4 => Err(Ordering::Less),
        j if j < 4 => Err(Ordering::Greater),
        _ => unreachable!(),
    };

    assert_eq!(Some(()), binary_search(1, 10, &closure));
    assert_eq!(None, binary_search(1, 3, &closure));
    assert_eq!(Some(()), binary_search(0, 44, &closure));
    assert_eq!(Some(()), binary_search(4, 125, &closure));
    assert_eq!(None, binary_search(6, 100, &closure));
}

pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr {
    match e.node {
        ast::ExprKind::InPlace(ref e, _) |
        ast::ExprKind::Call(ref e, _) |
        ast::ExprKind::Binary(_, ref e, _) |
        ast::ExprKind::Cast(ref e, _) |
        ast::ExprKind::Type(ref e, _) |
        ast::ExprKind::Assign(ref e, _) |
        ast::ExprKind::AssignOp(_, ref e, _) |
        ast::ExprKind::Field(ref e, _) |
        ast::ExprKind::TupField(ref e, _) |
        ast::ExprKind::Index(ref e, _) |
        ast::ExprKind::Range(Some(ref e), _, _) |
        ast::ExprKind::Try(ref e) => left_most_sub_expr(e),
        _ => e,
    }
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014, 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use boxed;
use boxed::BoxedType;
use enumeration;
use enumeration::{EnumType, IntrospectedEnum};
use enumeration::UnknownValue as UnknownEnumValue;
use flags;
use flags::{FlagsType, IntrospectedFlags, UnknownFlags};
use gstr::OwnedGStr;
use gtype::GType;
use object;
use object::ObjectType;
use types::{gboolean, gchar, gdouble, gfloat, gint, glong, gpointer};
use types::{guchar, guint, gulong};
use util::is_true;

use gobject as ffi;

use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::ops::Deref;

#[repr(C)]
#[unsafe_no_drop_flag]
pub struct Value(ffi::GValue);

impl Drop for Value {
    fn drop(&mut self) {
        if self.as_raw().g_type == 0 {
            return;
        }
        unsafe {
            ffi::g_value_unset(self.as_mut_raw());
        }
    }
}

impl Clone for Value {
    fn clone(&self) -> Value {
        Value(unsafe {
            let mut raw: ffi::GValue = mem::zeroed();
            ffi::g_value_init(&mut raw, self.as_raw().g_type);
            ffi::g_value_copy(self.as_raw(), &mut raw);
            raw
        })
    }
}

impl Value {
    pub fn new(g_type: GType) -> Value {
        Value(unsafe {
            let mut raw: ffi::GValue = mem::zeroed();
            ffi::g_value_init(&mut raw, g_type.to_raw());
            raw
        })
    }

    #[inline]
    fn as_raw(&self) -> &ffi::GValue {
        &self.0
    }

    #[inline]
    unsafe fn as_mut_raw(&mut self) -> &mut ffi::GValue {
        &mut self.0
    }

    #[inline]
    pub fn value_type(&self) -> GType {
        unsafe { GType::from_raw(self.as_raw().g_type) }
    }

    pub fn reset(&mut self) {
        unsafe {
            ffi::g_value_reset(self.as_mut_raw());
        }
    }

    pub fn get_boolean(&self) -> bool {
        is_true(unsafe { ffi::g_value_get_boolean(self.as_raw()) })
    }

    pub fn set_boolean(&mut self, val: bool) {
        unsafe { ffi::g_value_set_boolean(self.as_mut_raw(), val as gboolean) };
    }

    pub fn get_char(&self) -> gchar {
        unsafe { ffi::g_value_get_char(self.as_raw()) }
    }

    pub fn set_char(&mut self, val: gchar) {
        unsafe { ffi::g_value_set_char(self.as_mut_raw(), val) };
    }

    pub fn get_schar(&self) -> i8 {
        unsafe { ffi::g_value_get_schar(self.as_raw()) }
    }

    pub fn set_schar(&mut self, val: i8) {
        unsafe { ffi::g_value_set_schar(self.as_mut_raw(), val) };
    }

    pub fn get_uchar(&self) -> guchar {
        unsafe { ffi::g_value_get_uchar(self.as_raw()) }
    }

    pub fn set_uchar(&mut self, val: guchar) {
        unsafe { ffi::g_value_set_uchar(self.as_mut_raw(), val) };
    }

    pub fn get_int(&self) -> gint {
        unsafe { ffi::g_value_get_int(self.as_raw()) }
    }

    pub fn set_int(&mut self, val: gint) {
        unsafe { ffi::g_value_set_int(self.as_mut_raw(), val) };
    }

    pub fn get_uint(&self) -> guint {
        unsafe { ffi::g_value_get_uint(self.as_raw()) }
    }

    pub fn set_uint(&mut self, val: guint) {
        unsafe { ffi::g_value_set_uint(self.as_mut_raw(), val) };
    }

    pub fn get_long(&self) -> glong {
        unsafe { ffi::g_value_get_long(self.as_raw()) }
    }

    pub fn set_long(&mut self, val: glong) {
        unsafe { ffi::g_value_set_long(self.as_mut_raw(), val) };
    }

    pub fn get_ulong(&self) -> gulong {
        unsafe { ffi::g_value_get_ulong(self.as_raw()) }
    }

    pub fn set_ulong(&mut self, val: gulong) {
        unsafe { ffi::g_value_set_ulong(self.as_mut_raw(), val) };
    }

    pub fn get_int64(&self) -> i64 {
        unsafe { ffi::g_value_get_int64(self.as_raw()) }
    }

    pub fn set_int64(&mut self, val: i64) {
        unsafe { ffi::g_value_set_int64(self.as_mut_raw(), val) };
    }

    pub fn get_uint64(&self) -> u64 {
        unsafe { ffi::g_value_get_uint64(self.as_raw()) }
    }

    pub fn set_uint64(&mut self, val: u64) {
        unsafe { ffi::g_value_set_uint64(self.as_mut_raw(), val) };
    }

    pub fn get_float(&self) -> gfloat {
        unsafe { ffi::g_value_get_float(self.as_raw()) }
    }

    pub fn set_float(&mut self, val: gfloat) {
        unsafe { ffi::g_value_set_float(self.as_mut_raw(), val) };
    }

    pub fn get_double(&self) -> gdouble {
        unsafe { ffi::g_value_get_double(self.as_raw()) }
    }

    pub fn set_double(&mut self, val: gdouble) {
        unsafe { ffi::g_value_set_double(self.as_mut_raw(), val) };
    }

    fn assert_enum_type<T>(&self) where T: EnumType {
        debug_assert!(self.value_type() == enumeration::type_of::<T>(),
                      "GValue does not have the enumeration type {}",
                      enumeration::type_of::<T>().name());
    }

    pub fn get_enum<T>(&self) -> Result<T, UnknownEnumValue>
        where T: EnumType
    {
        self.assert_enum_type::<T>();
        unsafe {
            let v = ffi::g_value_get_enum(self.as_raw());
            IntrospectedEnum::from_int(v)
        }
    }

    pub fn set_enum<T>(&mut self, val: T) where T: EnumType {
        self.assert_enum_type::<T>();
        unsafe {
            ffi::g_value_set_enum(self.as_mut_raw(), val.to_int());
        }
    }

    fn assert_flags_type<T>(&self) where T: FlagsType {
        debug_assert!(self.value_type() == flags::type_of::<T>(),
                      "GValue does not have the flags type {}",
                      flags::type_of::<T>().name());
    }

    pub fn get_flags<T>(&self) -> Result<T, UnknownFlags>
        where T: FlagsType
    {
        self.assert_flags_type::<T>();
        unsafe {
            let v = ffi::g_value_get_flags(self.as_raw());
            IntrospectedFlags::from_uint(v)
        }
    }

    pub fn set_flags<T>(&mut self, val: T) where T: FlagsType {
        self.assert_flags_type::<T>();
        unsafe {
            ffi::g_value_set_flags(self.as_mut_raw(), val.to_uint());
        }
    }

    pub fn get_string(&self) -> Option<&CStr> {
        unsafe {
            let ptr = ffi::g_value_get_string(self.as_raw());
            if ptr.is_null() {
                return None;
            }
            Some(CStr::from_ptr(ptr))
        }
    }

    pub fn set_string(&mut self, val: &CStr) {
        unsafe { ffi::g_value_set_string(self.as_mut_raw(), val.as_ptr()) }
    }

    pub fn set_static_string(&mut self, val: &'static CStr) {
        unsafe {
            ffi::g_value_set_static_string(self.as_mut_raw(), val.as_ptr())
        }
    }

    pub fn take_string(&mut self, consumed: OwnedGStr) {
        unsafe {
            let ptr = consumed.as_ptr() as *mut gchar;
            ffi::g_value_take_string(self.as_mut_raw(), ptr);
            mem::forget(consumed);
        }
    }

    pub fn get_object<T>(&self) -> Option<&T>
        where T: ObjectType
    {
        assert!(self.value_type() == object::type_of::<T>(),
                "GValue does not have the object type {}",
                object::type_of::<T>().name());
        let p = unsafe { ffi::g_value_get_object(self.as_raw()) as *const T };
        if p.is_null() {
            return None;
        }
        Some(unsafe { mem::copy_lifetime(self, &*p) })
    }

    pub fn set_object<T>(&mut self, val: &T)
        where T: ObjectType
    {
        let p = val as *const _;
        unsafe { ffi::g_value_set_object(self.as_mut_raw(), p as gpointer) }
    }

    fn assert_boxed_type<T>(&self)
        where T: BoxedType
    {
        assert!(self.value_type() == boxed::type_of::<T>(),
                "GValue does not have the boxed type {}",
                boxed::type_of::<T>().name());
    }

    pub fn dup_boxed<T>(&self) -> Option<T>
        where T: BoxedType
    {
        self.assert_boxed_type::<T>();
        let p = unsafe { ffi::g_value_dup_boxed(self.as_raw()) };
        if p.is_null() {
            return None;
        }
        Some(unsafe {
            let boxed: T = BoxedType::from_ptr(p);
            boxed
        })
    }

    pub fn deref_boxed<T>(&self) -> Option<&<T as Deref>::Target>
        where T: BoxedType + Deref
    {
        self.assert_boxed_type::<T>();
        let p = unsafe { ffi::g_value_get_boxed(self.as_raw()) };
        if p.is_null() {
            return None;
        }
        unsafe {
            let boxed: T = BoxedType::from_ptr(p);
            let ret = Some(mem::copy_lifetime(self, &*boxed));

            // Lose the box by "subliming" it back into the raw pointer
            let q = boxed.into_ptr();
            debug_assert!(q == p,
                "BoxedType invariant violation: into_ptr does not reverse from_ptr");

            ret
        }
    }

    pub fn take_boxed<T>(&mut self, val: T) where T: BoxedType {
        unsafe {
            let p = val.into_ptr();
            ffi::g_value_take_boxed(self.as_mut_raw(), p);
        }
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let contents = unsafe {
            let ptr = ffi::g_strdup_value_contents(self.as_raw());
            OwnedGStr::from_ptr(ptr)
        };
        write!(f, "GValue({})", String::from_utf8_lossy(contents.to_bytes()))
    }
}
<commit_msg>Use transmute instead of copy_lifetime<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014, 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use boxed;
use boxed::BoxedType;
use enumeration;
use enumeration::{EnumType, IntrospectedEnum};
use enumeration::UnknownValue as UnknownEnumValue;
use flags;
use flags::{FlagsType, IntrospectedFlags, UnknownFlags};
use gstr::OwnedGStr;
use gtype::GType;
use object;
use object::ObjectType;
use types::{gboolean, gchar, gdouble, gfloat, gint, glong, gpointer};
use types::{guchar, guint, gulong};
use util::is_true;

use gobject as ffi;

use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::ops::Deref;

#[repr(C)]
#[unsafe_no_drop_flag]
pub struct Value(ffi::GValue);

impl Drop for Value {
    fn drop(&mut self) {
        if self.as_raw().g_type == 0 {
            return;
        }
        unsafe {
            ffi::g_value_unset(self.as_mut_raw());
        }
    }
}

impl Clone for Value {
    fn clone(&self) -> Value {
        Value(unsafe {
            let mut raw: ffi::GValue = mem::zeroed();
            ffi::g_value_init(&mut raw, self.as_raw().g_type);
            ffi::g_value_copy(self.as_raw(), &mut raw);
            raw
        })
    }
}

impl Value {
    pub fn new(g_type: GType) -> Value {
        Value(unsafe {
            let mut raw: ffi::GValue = mem::zeroed();
            ffi::g_value_init(&mut raw, g_type.to_raw());
            raw
        })
    }

    #[inline]
    fn as_raw(&self) -> &ffi::GValue {
        &self.0
    }

    #[inline]
    unsafe fn as_mut_raw(&mut self) -> &mut ffi::GValue {
        &mut self.0
    }

    #[inline]
    pub fn value_type(&self) -> GType {
        unsafe { GType::from_raw(self.as_raw().g_type) }
    }

    pub fn reset(&mut self) {
        unsafe {
            ffi::g_value_reset(self.as_mut_raw());
        }
    }

    pub fn get_boolean(&self) -> bool {
        is_true(unsafe { ffi::g_value_get_boolean(self.as_raw()) })
    }

    pub fn set_boolean(&mut self, val: bool) {
        unsafe { ffi::g_value_set_boolean(self.as_mut_raw(), val as gboolean) };
    }

    pub fn get_char(&self) -> gchar {
        unsafe { ffi::g_value_get_char(self.as_raw()) }
    }

    pub fn set_char(&mut self, val: gchar) {
        unsafe { ffi::g_value_set_char(self.as_mut_raw(), val) };
    }

    pub fn get_schar(&self) -> i8 {
        unsafe { ffi::g_value_get_schar(self.as_raw()) }
    }

    pub fn set_schar(&mut self, val: i8) {
        unsafe { ffi::g_value_set_schar(self.as_mut_raw(), val) };
    }

    pub fn get_uchar(&self) -> guchar {
        unsafe { ffi::g_value_get_uchar(self.as_raw()) }
    }

    pub fn set_uchar(&mut self, val: guchar) {
        unsafe { ffi::g_value_set_uchar(self.as_mut_raw(), val) };
    }

    pub fn get_int(&self) -> gint {
        unsafe { ffi::g_value_get_int(self.as_raw()) }
    }

    pub fn set_int(&mut self, val: gint) {
        unsafe { ffi::g_value_set_int(self.as_mut_raw(), val) };
    }

    pub fn get_uint(&self) -> guint {
        unsafe { ffi::g_value_get_uint(self.as_raw()) }
    }

    pub fn set_uint(&mut self, val: guint) {
        unsafe { ffi::g_value_set_uint(self.as_mut_raw(), val) };
    }

    pub fn get_long(&self) -> glong {
        unsafe { ffi::g_value_get_long(self.as_raw()) }
    }

    pub fn set_long(&mut self, val: glong) {
        unsafe { ffi::g_value_set_long(self.as_mut_raw(), val) };
    }

    pub fn get_ulong(&self) -> gulong {
        unsafe { ffi::g_value_get_ulong(self.as_raw()) }
    }

    pub fn set_ulong(&mut self, val: gulong) {
        unsafe { ffi::g_value_set_ulong(self.as_mut_raw(), val) };
    }

    pub fn get_int64(&self) -> i64 {
        unsafe { ffi::g_value_get_int64(self.as_raw()) }
    }

    pub fn set_int64(&mut self, val: i64) {
        unsafe { ffi::g_value_set_int64(self.as_mut_raw(), val) };
    }

    pub fn get_uint64(&self) -> u64 {
        unsafe { ffi::g_value_get_uint64(self.as_raw()) }
    }

    pub fn set_uint64(&mut self, val: u64) {
        unsafe { ffi::g_value_set_uint64(self.as_mut_raw(), val) };
    }

    pub fn get_float(&self) -> gfloat {
        unsafe { ffi::g_value_get_float(self.as_raw()) }
    }

    pub fn set_float(&mut self, val: gfloat) {
        unsafe { ffi::g_value_set_float(self.as_mut_raw(), val) };
    }

    pub fn get_double(&self) -> gdouble {
        unsafe { ffi::g_value_get_double(self.as_raw()) }
    }

    pub fn set_double(&mut self, val: gdouble) {
        unsafe { ffi::g_value_set_double(self.as_mut_raw(), val) };
    }

    fn assert_enum_type<T>(&self) where T: EnumType {
        debug_assert!(self.value_type() == enumeration::type_of::<T>(),
                      "GValue does not have the enumeration type {}",
                      enumeration::type_of::<T>().name());
    }

    pub fn get_enum<T>(&self) -> Result<T, UnknownEnumValue>
        where T: EnumType
    {
        self.assert_enum_type::<T>();
        unsafe {
            let v = ffi::g_value_get_enum(self.as_raw());
            IntrospectedEnum::from_int(v)
        }
    }

    pub fn set_enum<T>(&mut self, val: T) where T: EnumType {
        self.assert_enum_type::<T>();
        unsafe {
            ffi::g_value_set_enum(self.as_mut_raw(), val.to_int());
        }
    }

    fn assert_flags_type<T>(&self) where T: FlagsType {
        debug_assert!(self.value_type() == flags::type_of::<T>(),
                      "GValue does not have the flags type {}",
                      flags::type_of::<T>().name());
    }

    pub fn get_flags<T>(&self) -> Result<T, UnknownFlags>
        where T: FlagsType
    {
        self.assert_flags_type::<T>();
        unsafe {
            let v = ffi::g_value_get_flags(self.as_raw());
            IntrospectedFlags::from_uint(v)
        }
    }

    pub fn set_flags<T>(&mut self, val: T) where T: FlagsType {
        self.assert_flags_type::<T>();
        unsafe {
            ffi::g_value_set_flags(self.as_mut_raw(), val.to_uint());
        }
    }

    pub fn get_string(&self) -> Option<&CStr> {
        unsafe {
            let ptr = ffi::g_value_get_string(self.as_raw());
            if ptr.is_null() {
                return None;
            }
            Some(CStr::from_ptr(ptr))
        }
    }

    pub fn set_string(&mut self, val: &CStr) {
        unsafe { ffi::g_value_set_string(self.as_mut_raw(), val.as_ptr()) }
    }

    pub fn set_static_string(&mut self, val: &'static CStr) {
        unsafe {
            ffi::g_value_set_static_string(self.as_mut_raw(), val.as_ptr())
        }
    }

    pub fn take_string(&mut self, consumed: OwnedGStr) {
        unsafe {
            let ptr = consumed.as_ptr() as *mut gchar;
            ffi::g_value_take_string(self.as_mut_raw(), ptr);
            mem::forget(consumed);
        }
    }

    pub fn get_object<T>(&self) -> Option<&T>
        where T: ObjectType
    {
        assert!(self.value_type() == object::type_of::<T>(),
                "GValue does not have the object type {}",
                object::type_of::<T>().name());
        let p = unsafe { ffi::g_value_get_object(self.as_raw()) as *const T };
        if p.is_null() {
            return None;
        }
        Some(unsafe { mem::transmute(&*p) })
    }

    pub fn set_object<T>(&mut self, val: &T)
        where T: ObjectType
    {
        let p = val as *const _;
        unsafe { ffi::g_value_set_object(self.as_mut_raw(), p as gpointer) }
    }

    fn assert_boxed_type<T>(&self)
        where T: BoxedType
    {
        assert!(self.value_type() == boxed::type_of::<T>(),
                "GValue does not have the boxed type {}",
                boxed::type_of::<T>().name());
    }

    pub fn dup_boxed<T>(&self) -> Option<T>
        where T: BoxedType
    {
        self.assert_boxed_type::<T>();
        let p = unsafe { ffi::g_value_dup_boxed(self.as_raw()) };
        if p.is_null() {
            return None;
        }
        Some(unsafe {
            let boxed: T = BoxedType::from_ptr(p);
            boxed
        })
    }

    pub fn deref_boxed<T>(&self) -> Option<&<T as Deref>::Target>
        where T: BoxedType + Deref
    {
        self.assert_boxed_type::<T>();
        let p = unsafe { ffi::g_value_get_boxed(self.as_raw()) };
        if p.is_null() {
            return None;
        }
        unsafe {
            let boxed: T = BoxedType::from_ptr(p);
            let ret = Some(mem::transmute(&*boxed));

            // Lose the box by "subliming" it back into the raw pointer
            let q = boxed.into_ptr();
            debug_assert!(q == p,
                "BoxedType invariant violation: into_ptr does not reverse from_ptr");

            ret
        }
    }

    pub fn take_boxed<T>(&mut self, val: T) where T: BoxedType {
        unsafe {
            let p = val.into_ptr();
            ffi::g_value_take_boxed(self.as_mut_raw(), p);
        }
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let contents = unsafe {
            let ptr = ffi::g_strdup_value_contents(self.as_raw());
            OwnedGStr::from_ptr(ptr)
        };
        write!(f, "GValue({})", String::from_utf8_lossy(contents.to_bytes()))
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use chrono::{self, FixedOffset};
use formatted;
use linked_hash_map::LinkedHashMap;
use std::slice::Iter;
use decor::{Decor, Formatted, InternalString, Repr};
use key::Key;
use parser;
use nom;

/// Representation of a TOML Value (as part of a Key/Value Pair).
#[derive(Debug, Clone)]
pub enum Value {
    Integer(Formatted<i64>),
    String(Formatted<String>),
    Float(Formatted<f64>),
    DateTime(Formatted<DateTime>),
    Boolean(Formatted<bool>),
    Array(Array),
    InlineTable(InlineTable),
}

/// Type representing a TOML Date-Time,
/// payload of the `Value::DateTime` variant's value
#[derive(Eq, PartialEq, Clone, Debug, Hash)]
pub enum DateTime {
    OffsetDateTime(chrono::DateTime<FixedOffset>),
    LocalDateTime(chrono::NaiveDateTime),
    LocalDate(chrono::NaiveDate),
    LocalTime(chrono::NaiveTime),
}

/// Type representing a TOML array,
/// payload of the `Value::Array` variant's value
#[derive(Debug, Default, Clone)]
pub struct Array {
    pub(crate) values: Vec<Value>,
    // `trailing` represents whitespaces, newlines
    // and comments in an empty array or after the trailing comma
    pub(crate) trailing: InternalString,
    // prefix before `[` and suffix after `]`
    pub(crate) decor: Decor,
}

/// Type representing a TOML inline table,
/// payload of the `Value::InlineTable` variant
#[derive(Debug, Default, Clone)]
pub struct InlineTable {
    pub(crate) key_value_pairs: KeyValuePairs,
    // `preamble` represents whitespaces in an empty table
    pub(crate) preamble: InternalString,
    // prefix before `{` and suffix after `}`
    pub(crate) decor: Decor,
}

pub(crate) type KeyValuePairs = LinkedHashMap<InternalString, KeyValue>;

/// Type representing a TOML Key/Value Pair
#[derive(Debug, Clone)]
pub(crate) struct KeyValue {
    pub key: Repr,
    pub value: Value,
}

#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash)]
pub(crate) enum ValueType {
    None,
    Integer,
    String,
    Float,
    DateTime,
    Boolean,
    Array,
    InlineTable,
}

impl Array {
    pub fn len(&self) -> usize {
        self.values.len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn iter(&self) -> Iter<Value> {
        self.values.iter()
    }

    pub fn push<V: Into<Value>>(&mut self, v: V) -> bool {
        self.push_value(v.into(), true)
    }

    pub fn get(&mut self, index: usize) -> Option<&Value> {
        self.values.get(index)
    }

    pub fn remove(&mut self, index: usize) -> Value {
        self.values.remove(index)
    }

    /// Auto formats the array
    pub fn fmt(&mut self) {
        formatted::decorate_array(self);
    }

    pub(crate) fn push_value(&mut self, v: Value, decorate: bool) -> bool {
        let mut value = v.into();
        if !self.is_empty() && decorate {
            formatted::decorate(&mut value, " ", "");
        }
        if self.is_empty() || value.get_type() == self.value_type() {
            self.values.push(value);
            true
        } else {
            false
        }
    }

    pub(crate) fn value_type(&self) -> ValueType {
        if let Some(value) = self.values.get(0) {
            value.get_type()
        } else {
            ValueType::None
        }
    }
}

impl InlineTable {
    pub fn len(&self) -> usize {
        self.key_value_pairs.len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn iter<'a>(&'a self) -> Box<Iterator<Item = (&'a str, &'a Value)> + 'a> {
        Box::new(
            self.key_value_pairs
                .iter()
                .map(|(k, kv)| (&k[..], &kv.value)),
        )
    }

    pub fn sort(&mut self) {
        sort_key_value_pairs(&mut self.key_value_pairs);
    }

    pub fn contains_key(&self, key: &str) -> bool {
        self.key_value_pairs.contains_key(key)
    }

    pub fn insert<V: Into<Value>>(&mut self, key: Key, value: V) -> Option<Value> {
        let kv = formatted::to_key_value(key.raw(), value.into());
        self.key_value_pairs.insert(key.into(), kv).map(|p| p.value)
    }

    pub fn append(&mut self, other: &mut InlineTable) {
        while let Some((k, kv)) = other.key_value_pairs.pop_front() {
            self.key_value_pairs.insert(k, kv);
        }
    }

    /// Auto formats the table
    pub fn fmt(&mut self) {
        formatted::decorate_inline_table(self);
    }

    pub fn remove(&mut self, key: &str) -> Option<Value> {
        self.key_value_pairs.remove(key).map(|kv| kv.value)
    }

    pub fn get(&self, key: &str) -> Option<&Value> {
        self.key_value_pairs.get(key).map(|kv| &kv.value)
    }

    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
        self.key_value_pairs.get_mut(key).map(|kv| &mut kv.value)
    }
}

/// Downcasting
impl DateTime {
    pub fn as_offset_date_time(&self) -> Option<&chrono::DateTime<FixedOffset>> {
        match *self {
            DateTime::OffsetDateTime(ref dt) => Some(dt),
            _ => None,
        }
    }
    pub fn as_local_date_time(&self) -> Option<&chrono::NaiveDateTime> {
        match *self {
            DateTime::LocalDateTime(ref dt) => Some(dt),
            _ => None,
        }
    }
    pub fn as_local_date(&self) -> Option<&chrono::NaiveDate> {
        match *self {
            DateTime::LocalDate(ref d) => Some(d),
            _ => None,
        }
    }
    pub fn as_local_time(&self) -> Option<&chrono::NaiveTime> {
        match *self {
            DateTime::LocalTime(ref t) => Some(t),
            _ => None,
        }
    }
    pub fn is_offset_date_time(&self) -> bool {
        self.as_offset_date_time().is_some()
    }
    pub fn is_local_date_time(&self) -> bool {
        self.as_local_date_time().is_some()
    }
    pub fn is_local_date(&self) -> bool {
        self.as_local_date().is_some()
    }
    pub fn is_local_time(&self) -> bool {
        self.as_local_time().is_some()
    }
}

/// Downcasting
impl Value {
    pub fn as_integer(&self) -> Option<i64> {
        match *self {
            Value::Integer(ref value) => Some(*value.value()),
            _ => None,
        }
    }

    pub fn is_integer(&self) -> bool {
        self.as_integer().is_some()
    }

    pub fn as_float(&self) -> Option<f64> {
        match *self {
            Value::Float(ref value) => Some(*value.value()),
            _ => None,
        }
    }

    pub fn is_float(&self) -> bool {
        self.as_float().is_some()
    }

    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Boolean(ref value) => Some(*value.value()),
            _ => None,
        }
    }

    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref value) => Some(value.value()),
            _ => None,
        }
    }

    pub fn is_str(&self) -> bool {
        self.as_str().is_some()
    }

    pub fn as_date_time(&self) -> Option<&DateTime> {
        match *self {
            Value::DateTime(ref value) => Some(value.value()),
            _ => None,
        }
    }

    pub fn is_date_time(&self) -> bool {
        self.as_date_time().is_some()
    }

    pub fn as_array(&self) -> Option<&Array> {
        match *self {
            Value::Array(ref value) => Some(value),
            _ => None,
        }
    }

    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        match *self {
            Value::Array(ref mut value) => Some(value),
            _ => None,
        }
    }

    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    pub fn as_inline_table(&self) -> Option<&InlineTable> {
        match *self {
            Value::InlineTable(ref value) => Some(value),
            _ => None,
        }
    }

    pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
        match *self {
            Value::InlineTable(ref mut value) => Some(value),
            _ => None,
        }
    }

    pub fn is_inline_table(&self) -> bool {
        self.as_inline_table().is_some()
    }

    fn get_type(&self) -> ValueType {
        match *self {
            Value::Integer(..) => ValueType::Integer,
            Value::String(..) => ValueType::String,
            Value::Float(..) => ValueType::Float,
            Value::DateTime(..) => ValueType::DateTime,
            Value::Boolean(..) => ValueType::Boolean,
            Value::Array(..) => ValueType::Array,
            Value::InlineTable(..) => ValueType::InlineTable,
        }
    }
}

pub(crate) fn sort_key_value_pairs(pairs: &mut KeyValuePairs) {
    let mut keys: Vec<InternalString> = pairs.keys().cloned().collect();
    keys.sort();
    for key in keys {
        pairs.get_refresh(&key);
    }
}

impl FromStr for Value {
    type Err = parser::Error;

    /// Parses a value from a &str
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let parsed = parser::value(parser::Span::new(s));
        match parsed {
            nom::IResult::Done(i, value) => if i.fragment.is_empty() {
                Ok(value)
            } else {
                Err(Self::Err::new(parser::ErrorKind::InvalidValue, i))
            },
            nom::IResult::Error(e) => Err(parser::to_error(&e)),
            _ => unreachable!("value should be complete"),
        }
    }
}
<commit_msg>feat(try_insert): add try_insert into inline_table<commit_after>use std::str::FromStr;
use chrono::{self, FixedOffset};
use formatted;
use linked_hash_map::LinkedHashMap;
use std::slice::Iter;
use decor::{Decor, Formatted, InternalString, Repr};
use key::Key;
use parser;
use nom;

/// Representation of a TOML Value (as part of a Key/Value Pair).
#[derive(Debug, Clone)]
pub enum Value {
    Integer(Formatted<i64>),
    String(Formatted<String>),
    Float(Formatted<f64>),
    DateTime(Formatted<DateTime>),
    Boolean(Formatted<bool>),
    Array(Array),
    InlineTable(InlineTable),
}

/// Type representing a TOML Date-Time,
/// payload of the `Value::DateTime` variant's value
#[derive(Eq, PartialEq, Clone, Debug, Hash)]
pub enum DateTime {
    OffsetDateTime(chrono::DateTime<FixedOffset>),
    LocalDateTime(chrono::NaiveDateTime),
    LocalDate(chrono::NaiveDate),
    LocalTime(chrono::NaiveTime),
}

/// Type representing a TOML array,
/// payload of the `Value::Array` variant's value
#[derive(Debug, Default, Clone)]
pub struct Array {
    pub(crate) values: Vec<Value>,
    // `trailing` represents whitespaces, newlines
    // and comments in an empty array or after the trailing comma
    pub(crate) trailing: InternalString,
    // prefix before `[` and suffix after `]`
    pub(crate) decor: Decor,
}

/// Type representing a TOML inline table,
/// payload of the `Value::InlineTable` variant
#[derive(Debug, Default, Clone)]
pub struct InlineTable {
    pub(crate) key_value_pairs: KeyValuePairs,
    // `preamble` represents whitespaces in an empty table
    pub(crate) preamble: InternalString,
    // prefix before `{` and suffix after `}`
    pub(crate) decor: Decor,
}

pub(crate) type KeyValuePairs = LinkedHashMap<InternalString, KeyValue>;

/// Type representing a TOML Key/Value Pair
#[derive(Debug, Clone)]
pub(crate) struct KeyValue {
    pub key: Repr,
    pub value: Value,
}

#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash)]
pub(crate) enum ValueType {
    None,
    Integer,
    String,
    Float,
    DateTime,
    Boolean,
    Array,
    InlineTable,
}

impl Array {
    pub fn len(&self) -> usize {
        self.values.len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn iter(&self) -> Iter<Value> {
        self.values.iter()
    }

    pub fn push<V: Into<Value>>(&mut self, v: V) -> bool {
        self.push_value(v.into(), true)
    }

    pub fn get(&mut self, index: usize) -> Option<&Value> {
        self.values.get(index)
    }

    pub fn remove(&mut self, index: usize) -> Value {
        self.values.remove(index)
    }

    /// Auto formats the array
    pub fn fmt(&mut self) {
        formatted::decorate_array(self);
    }

    pub(crate) fn push_value(&mut self, v: Value, decorate: bool) -> bool {
        let mut value = v.into();
        if !self.is_empty() && decorate {
            formatted::decorate(&mut value, " ", "");
        }
        if self.is_empty() || value.get_type() == self.value_type() {
            self.values.push(value);
            true
        } else {
            false
        }
    }

    pub(crate) fn value_type(&self) -> ValueType {
        if let Some(value) = self.values.get(0) {
            value.get_type()
        } else {
            ValueType::None
        }
    }
}

impl InlineTable {
    pub fn len(&self) -> usize {
        self.key_value_pairs.len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn iter<'a>(&'a self) -> Box<Iterator<Item = (&'a str, &'a Value)> + 'a> {
        Box::new(
            self.key_value_pairs
                .iter()
                .map(|(k, kv)| (&k[..], &kv.value)),
        )
    }

    pub fn sort(&mut self) {
        sort_key_value_pairs(&mut self.key_value_pairs);
    }

    pub fn contains_key(&self, key: &str) -> bool {
        self.key_value_pairs.contains_key(key)
    }

    pub fn try_insert<V: Into<Value>>(&mut self, key: Key, value: V) -> &mut Value {
        let kv = formatted::to_key_value(key.raw(), value.into());
        &mut self.key_value_pairs.entry(key.into()).or_insert(kv).value
    }

    pub fn insert<V: Into<Value>>(&mut self, key: Key, value: V) -> Option<Value> {
        let kv = formatted::to_key_value(key.raw(), value.into());
        self.key_value_pairs.insert(key.into(), kv).map(|p| p.value)
    }

    pub fn append(&mut self, other: &mut InlineTable) {
        while let Some((k, kv)) = other.key_value_pairs.pop_front() {
            self.key_value_pairs.insert(k, kv);
        }
    }

    /// Auto formats the table
    pub fn fmt(&mut self) {
        formatted::decorate_inline_table(self);
    }

    pub fn remove(&mut self, key: &str) -> Option<Value> {
        self.key_value_pairs.remove(key).map(|kv| kv.value)
    }

    pub fn get(&self, key: &str) -> Option<&Value> {
        self.key_value_pairs.get(key).map(|kv| &kv.value)
    }

    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
        self.key_value_pairs.get_mut(key).map(|kv| &mut kv.value)
    }
}

/// Downcasting
impl DateTime {
    pub fn as_offset_date_time(&self) -> Option<&chrono::DateTime<FixedOffset>> {
        match *self {
            DateTime::OffsetDateTime(ref dt) => Some(dt),
            _ => None,
        }
    }
    pub fn as_local_date_time(&self) -> Option<&chrono::NaiveDateTime> {
        match *self {
            DateTime::LocalDateTime(ref dt) => Some(dt),
            _ => None,
        }
    }
    pub fn as_local_date(&self) -> Option<&chrono::NaiveDate> {
        match *self {
            DateTime::LocalDate(ref d) => Some(d),
            _ => None,
        }
    }
    pub fn as_local_time(&self) -> Option<&chrono::NaiveTime> {
        match *self {
            DateTime::LocalTime(ref t) => Some(t),
            _ => None,
        }
    }
    pub fn is_offset_date_time(&self) -> bool {
        self.as_offset_date_time().is_some()
    }
    pub fn is_local_date_time(&self) -> bool {
        self.as_local_date_time().is_some()
    }
    pub fn is_local_date(&self) -> bool {
        self.as_local_date().is_some()
    }
    pub fn is_local_time(&self) -> bool {
        self.as_local_time().is_some()
    }
}

/// Downcasting
impl Value {
    pub fn as_integer(&self) -> Option<i64> {
        match *self {
            Value::Integer(ref value) => Some(*value.value()),
            _ => None,
        }
    }

    pub fn is_integer(&self) -> bool {
        self.as_integer().is_some()
    }

    pub fn as_float(&self) -> Option<f64> {
        match *self {
            Value::Float(ref value) => Some(*value.value()),
            _ => None,
        }
    }

    pub fn is_float(&self) -> bool {
        self.as_float().is_some()
    }

    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Boolean(ref value) => Some(*value.value()),
            _ => None,
        }
    }

    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref value) => Some(value.value()),
            _ => None,
        }
    }

    pub fn is_str(&self) -> bool {
        self.as_str().is_some()
    }

    pub fn as_date_time(&self) -> Option<&DateTime> {
        match *self {
            Value::DateTime(ref value) => Some(value.value()),
            _ => None,
        }
    }

    pub fn is_date_time(&self) -> bool {
        self.as_date_time().is_some()
    }

    pub fn as_array(&self) -> Option<&Array> {
        match *self {
            Value::Array(ref value) => Some(value),
            _ => None,
        }
    }

    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        match *self {
            Value::Array(ref mut value) => Some(value),
            _ => None,
        }
    }

    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    pub fn as_inline_table(&self) -> Option<&InlineTable> {
        match *self {
            Value::InlineTable(ref value) => Some(value),
            _ => None,
        }
    }

    pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
        match *self {
            Value::InlineTable(ref mut value) => Some(value),
            _ => None,
        }
    }

    pub fn is_inline_table(&self) -> bool {
        self.as_inline_table().is_some()
    }

    fn get_type(&self) -> ValueType {
        match *self {
            Value::Integer(..) => ValueType::Integer,
            Value::String(..) => ValueType::String,
            Value::Float(..) => ValueType::Float,
            Value::DateTime(..) => ValueType::DateTime,
            Value::Boolean(..) => ValueType::Boolean,
            Value::Array(..) => ValueType::Array,
            Value::InlineTable(..) => ValueType::InlineTable,
        }
    }
}

pub(crate) fn sort_key_value_pairs(pairs: &mut KeyValuePairs) {
    let mut keys: Vec<InternalString> = pairs.keys().cloned().collect();
    keys.sort();
    for key in keys {
        pairs.get_refresh(&key);
    }
}

impl FromStr for Value {
    type Err = parser::Error;

    /// Parses a value from a &str
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let parsed = parser::value(parser::Span::new(s));
        match parsed {
            nom::IResult::Done(i, value) => if i.fragment.is_empty() {
                Ok(value)
            } else {
                Err(Self::Err::new(parser::ErrorKind::InvalidValue, i))
            },
            nom::IResult::Error(e) => Err(parser::to_error(&e)),
            _ => unreachable!("value should be complete"),
        }
    }
}
<|endoftext|>