<commit_before>use std::io;

fn main() {
	let mut max_lengths: Vec<uint> = Vec::new();
	let mut inputs: Vec<Vec<String>> = Vec::new();

	for line in io::stdin().lines() {
		let mut input = line.unwrap();
		input.pop_char();
		let split_input: Vec<String> = input.as_slice().split('$').map(|s| s.to_string()).collect();
		inputs.push(split_input.clone());
		let v: Vec<uint> = split_input.iter().map(|chunk| chunk.len() ).collect();

		for i in range(0u, v.len()) {
			if i < max_lengths.len() {
				*max_lengths.get_mut(i) = std::cmp::max(max_lengths[i], v[i]);
			} else {
				max_lengths.push(v[i]);
			}
		}
	}

	// left aligned
	for i in range(0u, inputs.len()) {
		for j in range(0u, inputs[i].len()) {
			print!("{0:<1$}", inputs[i][j], 1 + max_lengths[j]);
		}
		println!("");
	}
	println!("");
	// right aligned
	for i in range(0u, inputs.len()) {
		for j in range(0u, inputs[i].len()) {
			print!("{0:>1$}", inputs[i][j], 1 + max_lengths[j]);
		}
		println!("");
	}
	println!("");
	// center aligned
	for i in range(0u, inputs.len()) {
		for j in range(0u, inputs[i].len()) {
			let ref string: String = inputs[i][j];
			let spaces: uint = 1 + max_lengths[j] - string.len();
			for k in range(0u, spaces >> 2) {
				print!(" ");
			}
			print!("{}", string);
			for k in range(0u, spaces - (spaces >> 2)) {
				print!(" ");
			}
		}
		println!("");
	}
}<commit_msg>move stuff around, fix the >>2 mistake, add a test<commit_after>fn main() {
	let text: String = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$\nare$delineated$by$a$single$'dollar'$character,$write$a$program\nthat$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\ncolumn$are$separated$by$at$least$one$space.\nFurther,$allow$for$each$word$in$a$column$to$be$either$left$\njustified,$right$justified,$or$center$justified$within$its$column.\n".to_string();
	let (chunks, max_lengths) = align_columns(&text);
	print_aligned_columns(&chunks, &max_lengths);
}

fn align_columns(text: &String) -> (Vec<Vec<String>>, Vec<uint>) {
	let mut lines: Vec<String> = text.as_slice().split('\n').map(|s| s.to_string()).collect();
	let mut max_lengths: Vec<uint> = Vec::new();
	let mut chunks: Vec<Vec<String>> = Vec::new();

	for i in range(0u, lines.len()) {
		let input = lines.get_mut(i);
		let split_input: Vec<String> = input.as_slice().split('$').map(|s| s.to_string()).collect();
		chunks.push(split_input.clone());
		let v: Vec<uint> = split_input.iter().map(|chunk| chunk.len() ).collect();

		for i in range(0u, v.len()) {
			if i < max_lengths.len() {
				*max_lengths.get_mut(i) = std::cmp::max(max_lengths[i], v[i]);
			} else {
				max_lengths.push(v[i]);
			}
		}
	}

	(chunks, max_lengths)
}

fn print_aligned_columns(chunks: &Vec<Vec<String>>, max_lengths: &Vec<uint>) {
	// left aligned
	for i in range(0u, chunks.len()) {
		for j in range(0u, chunks[i].len()) {
			print!("{0:<1$}", chunks[i][j], 1 + max_lengths[j]);
		}
		println!("");
	}
	println!("");
	// right aligned
	for i in range(0u, chunks.len()) {
		for j in range(0u, chunks[i].len()) {
			print!("{0:>1$}", chunks[i][j], 1 + max_lengths[j]);
		}
		println!("");
	}
	println!("");
	// center aligned
	for i in range(0u, chunks.len()) {
		for j in range(0u, chunks[i].len()) {
			let ref string: String = chunks[i][j];
			let spaces: uint = 1 + max_lengths[j] - string.len();
			for k in range(0u, spaces>>1) {
				print!(" ");
			}
			print!("{}", string);
			for k in range(0u, spaces - (spaces>>1)) {
				print!(" ");
			}
		}
		println!("");
	}
}

#[test]
fn test_result() {
	let text: String = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$\nare$delineated$by$a$single$'dollar'$character,$write$a$program\nthat$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\ncolumn$are$separated$by$at$least$one$space.\nFurther,$allow$for$each$word$in$a$column$to$be$either$left$\njustified,$right$justified,$or$center$justified$within$its$column.\n".to_string();
	let (chunks, max_lengths) = align_columns(&text);
	for chunkset in chunks.iter() {
		// the number of words in a chunkset is <= the number of values in max_lengths
		assert!(chunkset.len() <= max_lengths.len());
		for j in range(0u, chunkset.len()) {
			// a word in a chunkset cannot be longer than max_lengths
			assert!(chunkset[j].len() <= max_lengths[j]);
		}
	}
	print_aligned_columns(&chunks, &max_lengths);
}<|endoftext|>


<commit_before>use std::borrow;
use std::cmp::Ordering;
use std::fmt;

#[cfg(feature = "object_sorted")]
use std::collections::BTreeMap;

#[cfg(not(any(feature = "object_sorted")))]
use std::collections::HashMap;

use super::Scalar;

#[cfg(feature = "object_sorted")]
type MapImpl<K, V> = BTreeMap<K, V>;

#[cfg(not(any(feature = "object_sorted")))]
type MapImpl<K, V> = HashMap<K, V>;

/// An enum to represent different value types
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Value {
    /// A scalar value.
    Scalar(Scalar),
    /// A sequence of `Value`s.
    Array(Array),
    /// A sequence of key/`Value` pairs.
    Object(Object),
    /// Nothing.
    Nil,
}

/// Type representing a Liquid array, payload of the `Value::Array` variant
pub type Array = Vec<Value>;

/// Type representing a Liquid object, payload of the `Value::Object` variant
pub type Object = MapImpl<borrow::Cow<'static, str>, Value>;

impl Value {
    /// Create as a `Scalar`.
    pub fn scalar<T: Into<Scalar>>(value: T) -> Self {
        Value::Scalar(Scalar::new(value))
    }

    /// Create as an `Array`.
    pub fn array<I: IntoIterator<Item = Self>>(iter: I) -> Self {
        let v: Array = iter.into_iter().collect();
        Value::Array(v)
    }

    /// Create as nothing.
    pub fn nil() -> Self {
        Value::Nil
    }

    /// Interpret as a string.
    pub fn to_str(&self) -> borrow::Cow<str> {
        match *self {
            Value::Scalar(ref x) => x.to_str(),
            Value::Array(ref x) => {
                let arr: Vec<String> = x.iter().map(|v| v.to_string()).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Object(ref x) => {
                let arr: Vec<String> = x.iter().map(|(k, v)| format!("{}: {}", k, v)).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Nil => borrow::Cow::Borrowed(""),
        }
    }

    /// Extracts the scalar value if it is a scalar.
    pub fn as_scalar(&self) -> Option<&Scalar> {
        match *self {
            Value::Scalar(ref s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is a scalar
    pub fn is_scalar(&self) -> bool {
        self.as_scalar().is_some()
    }

    /// Extracts the array value if it is an array.
    pub fn as_array(&self) -> Option<&Array> {
        match *self {
            Value::Array(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the array value if it is an array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        match *self {
            Value::Array(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an array
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Extracts the object value if it is a object.
    pub fn as_object(&self) -> Option<&Object> {
        match *self {
            Value::Object(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the object value if it is a object.
    pub fn as_object_mut(&mut self) -> Option<&mut Object> {
        match *self {
            Value::Object(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an object
    pub fn is_object(&self) -> bool {
        self.as_object().is_some()
    }

    /// Tests whether this value is nil
    pub fn is_nil(&self) -> bool {
        match *self {
            Value::Nil => true,
            _ => false,
        }
    }

    /// Evaluate using Liquid "truthiness"
    pub fn is_truthy(&self) -> bool {
        // encode Ruby truthiness: all values except false and nil are true
        match *self {
            Value::Scalar(ref x) => x.is_truthy(),
            Value::Nil => false,
            _ => true,
        }
    }

    /// Whether a default constructed value.
    pub fn is_default(&self) -> bool {
        match *self {
            Value::Scalar(ref x) => x.is_default(),
            Value::Nil => true,
            Value::Array(ref x) => x.is_empty(),
            Value::Object(ref x) => x.is_empty(),
        }
    }

    /// Report the data type (generally for error reporting).
    pub fn type_name(&self) -> &'static str {
        match *self {
            Value::Scalar(ref x) => x.type_name(),
            Value::Nil => "nil",
            Value::Array(_) => "array",
            Value::Object(_) => "object",
        }
    }

    /// Access a contained `Value`.
    pub fn get<'i, I: Into<&'i Scalar>>(&self, index: I) -> Option<&Self> {
        let index: &Scalar = index.into();
        self.get_index(index)
    }

    fn get_index(&self, index: &Scalar) -> Option<&Self> {
        match *self {
            Value::Array(ref x) => {
                if let Some(index) = index.to_integer() {
                    let index = if 0 <= index {
                        index as isize
                    } else {
                        (x.len() as isize) + (index as isize)
                    };
                    x.get(index as usize)
                } else {
                    match &*index.to_str() {
                        "first" => x.get(0),
                        "last" => x.get(x.len() - 1),
                        _ => None,
                    }
                }
            }
            Value::Object(ref x) => x.get(index.to_str().as_ref()),
            _ => None,
        }
    }
}

impl Default for Value {
    fn default() -> Self {
        Self::nil()
    }
}

impl PartialEq<Value> for Value {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
            (&Value::Array(ref x), &Value::Array(ref y)) => x == y,
            (&Value::Object(ref x), &Value::Object(ref y)) => x == y,
            (&Value::Nil, &Value::Nil) => true,

            // encode Ruby truthiness: all values except false and nil are true
            (&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
                !b.to_bool().unwrap_or(true)
            }
            (_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),

            _ => false,
        }
    }
}

impl Eq for Value {}

impl PartialOrd<Value> for Value {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
            (&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
            (&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
            _ => None,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let data = self.to_str();
        write!(f, "{}", data)
    }
}

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

    #[test]
    fn test_to_string_scalar() {
        let val = Value::scalar(42f64);
        assert_eq!(&val.to_string(), "42");
    }

    #[test]
    fn test_to_string_array() {
        let val = Value::Array(vec![
            Value::scalar(3f64),
            Value::scalar("test"),
            Value::scalar(5.3),
        ]);
        assert_eq!(&val.to_string(), "3, test, 5.3");
    }

    // TODO make a test for object, remember values are in arbitrary orders in HashMaps

    #[test]
    fn test_to_string_nil() {
        assert_eq!(&Value::nil().to_string(), "");
    }

    #[test]
    fn scalar_equality() {
        assert_eq!(Value::scalar("alpha"), Value::scalar("alpha"));
        assert_eq!(Value::scalar(""), Value::scalar(""));
        assert!(Value::scalar("alpha") != Value::scalar("beta"));
        assert!(Value::scalar("beta") != Value::scalar("alpha"));
    }

    #[test]
    fn scalars_have_ruby_truthiness() {
        // all strings in ruby are true
        assert_eq!(Value::scalar(true), Value::scalar("All strings are truthy"));
        assert_eq!(Value::scalar(true), Value::scalar(""));
        assert!(Value::scalar("").is_truthy());

        assert_eq!(Value::scalar(true), Value::scalar(true));
        assert!(Value::scalar(true) != Value::scalar(false));
    }

    #[test]
    fn array_equality() {
        let a = Value::Array(vec![Value::scalar("one"), Value::scalar("two")]);
        let b = Value::Array(vec![Value::scalar("alpha"), Value::scalar("beta")]);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn arrays_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Array(Vec::new()));
        assert!(Value::Array(Vec::new()).is_truthy());
    }

    #[test]
    fn object_equality() {
        let a: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
        ]
            .into_iter()
            .cloned()
            .collect();
        let a = Value::Object(a);

        let b: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
            ("gamma".into(), Value::Array(vec![])),
        ]
            .into_iter()
            .cloned()
            .collect();
        let b = Value::Object(b);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn objects_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Object(Object::new()));
        assert!(Value::Object(Object::new()).is_truthy());
    }

    #[test]
    fn nil_equality() {
        assert_eq!(Value::Nil, Value::Nil);
    }

    #[test]
    fn nils_have_ruby_truthiness() {
        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(!Value::Nil.is_truthy());

        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(Value::scalar(true) != Value::Nil);
        assert!(Value::scalar("") != Value::Nil);
    }
}
<commit_msg>feat(value): Allow moving into constituent types<commit_after>use std::borrow;
use std::cmp::Ordering;
use std::fmt;

#[cfg(feature = "object_sorted")]
use std::collections::BTreeMap;

#[cfg(not(any(feature = "object_sorted")))]
use std::collections::HashMap;

use super::Scalar;

#[cfg(feature = "object_sorted")]
type MapImpl<K, V> = BTreeMap<K, V>;

#[cfg(not(any(feature = "object_sorted")))]
type MapImpl<K, V> = HashMap<K, V>;

/// An enum to represent different value types
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Value {
    /// A scalar value.
    Scalar(Scalar),
    /// A sequence of `Value`s.
    Array(Array),
    /// A sequence of key/`Value` pairs.
    Object(Object),
    /// Nothing.
    Nil,
}

/// Type representing a Liquid array, payload of the `Value::Array` variant
pub type Array = Vec<Value>;

/// Type representing a Liquid object, payload of the `Value::Object` variant
pub type Object = MapImpl<borrow::Cow<'static, str>, Value>;

impl Value {
    /// Create as a `Scalar`.
    pub fn scalar<T: Into<Scalar>>(value: T) -> Self {
        Value::Scalar(Scalar::new(value))
    }

    /// Create as an `Array`.
    pub fn array<I: IntoIterator<Item = Self>>(iter: I) -> Self {
        let v: Array = iter.into_iter().collect();
        Value::Array(v)
    }

    /// Create as nothing.
    pub fn nil() -> Self {
        Value::Nil
    }

    /// Interpret as a string.
    pub fn to_str(&self) -> borrow::Cow<str> {
        match *self {
            Value::Scalar(ref x) => x.to_str(),
            Value::Array(ref x) => {
                let arr: Vec<String> = x.iter().map(|v| v.to_string()).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Object(ref x) => {
                let arr: Vec<String> = x.iter().map(|(k, v)| format!("{}: {}", k, v)).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Nil => borrow::Cow::Borrowed(""),
        }
    }

    /// Extracts the scalar value if it is a scalar.
    pub fn as_scalar(&self) -> Option<&Scalar> {
        match *self {
            Value::Scalar(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the scalar value if it is a scalar.
    pub fn into_scalar(self) -> Option<Scalar> {
        match self {
            Value::Scalar(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is a scalar
    pub fn is_scalar(&self) -> bool {
        self.as_scalar().is_some()
    }

    /// Extracts the array value if it is an array.
    pub fn as_array(&self) -> Option<&Array> {
        match *self {
            Value::Array(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the array value if it is an array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        match *self {
            Value::Array(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the array value if it is an array.
    pub fn into_array(self) -> Option<Array> {
        match self {
            Value::Array(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an array
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Extracts the object value if it is a object.
    pub fn as_object(&self) -> Option<&Object> {
        match *self {
            Value::Object(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the object value if it is a object.
    pub fn as_object_mut(&mut self) -> Option<&mut Object> {
        match *self {
            Value::Object(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the object value if it is a object.
    pub fn into_object(self) -> Option<Object> {
        match self {
            Value::Object(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an object
    pub fn is_object(&self) -> bool {
        self.as_object().is_some()
    }

    /// Extracts the nil value if it is nil
    pub fn as_nil(&self) -> Option<()> {
        match *self {
            Value::Nil => Some(()),
            _ => None,
        }
    }

    /// Tests whether this value is nil
    pub fn is_nil(&self) -> bool {
        match *self {
            Value::Nil => true,
            _ => false,
        }
    }

    /// Evaluate using Liquid "truthiness"
    pub fn is_truthy(&self) -> bool {
        // encode Ruby truthiness: all values except false and nil are true
        match *self {
            Value::Scalar(ref x) => x.is_truthy(),
            Value::Nil => false,
            _ => true,
        }
    }

    /// Whether a default constructed value.
    pub fn is_default(&self) -> bool {
        match *self {
            Value::Scalar(ref x) => x.is_default(),
            Value::Nil => true,
            Value::Array(ref x) => x.is_empty(),
            Value::Object(ref x) => x.is_empty(),
        }
    }

    /// Report the data type (generally for error reporting).
    pub fn type_name(&self) -> &'static str {
        match *self {
            Value::Scalar(ref x) => x.type_name(),
            Value::Nil => "nil",
            Value::Array(_) => "array",
            Value::Object(_) => "object",
        }
    }

    /// Access a contained `Value`.
    pub fn get<'i, I: Into<&'i Scalar>>(&self, index: I) -> Option<&Self> {
        let index: &Scalar = index.into();
        self.get_index(index)
    }

    fn get_index(&self, index: &Scalar) -> Option<&Self> {
        match *self {
            Value::Array(ref x) => {
                if let Some(index) = index.to_integer() {
                    let index = if 0 <= index {
                        index as isize
                    } else {
                        (x.len() as isize) + (index as isize)
                    };
                    x.get(index as usize)
                } else {
                    match &*index.to_str() {
                        "first" => x.get(0),
                        "last" => x.get(x.len() - 1),
                        _ => None,
                    }
                }
            }
            Value::Object(ref x) => x.get(index.to_str().as_ref()),
            _ => None,
        }
    }
}

impl Default for Value {
    fn default() -> Self {
        Self::nil()
    }
}

impl PartialEq<Value> for Value {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
            (&Value::Array(ref x), &Value::Array(ref y)) => x == y,
            (&Value::Object(ref x), &Value::Object(ref y)) => x == y,
            (&Value::Nil, &Value::Nil) => true,

            // encode Ruby truthiness: all values except false and nil are true
            (&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
                !b.to_bool().unwrap_or(true)
            }
            (_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),

            _ => false,
        }
    }
}

impl Eq for Value {}

impl PartialOrd<Value> for Value {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
            (&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
            (&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
            _ => None,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let data = self.to_str();
        write!(f, "{}", data)
    }
}

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

    #[test]
    fn test_to_string_scalar() {
        let val = Value::scalar(42f64);
        assert_eq!(&val.to_string(), "42");
    }

    #[test]
    fn test_to_string_array() {
        let val = Value::Array(vec![
            Value::scalar(3f64),
            Value::scalar("test"),
            Value::scalar(5.3),
        ]);
        assert_eq!(&val.to_string(), "3, test, 5.3");
    }

    // TODO make a test for object, remember values are in arbitrary orders in HashMaps

    #[test]
    fn test_to_string_nil() {
        assert_eq!(&Value::nil().to_string(), "");
    }

    #[test]
    fn scalar_equality() {
        assert_eq!(Value::scalar("alpha"), Value::scalar("alpha"));
        assert_eq!(Value::scalar(""), Value::scalar(""));
        assert!(Value::scalar("alpha") != Value::scalar("beta"));
        assert!(Value::scalar("beta") != Value::scalar("alpha"));
    }

    #[test]
    fn scalars_have_ruby_truthiness() {
        // all strings in ruby are true
        assert_eq!(Value::scalar(true), Value::scalar("All strings are truthy"));
        assert_eq!(Value::scalar(true), Value::scalar(""));
        assert!(Value::scalar("").is_truthy());

        assert_eq!(Value::scalar(true), Value::scalar(true));
        assert!(Value::scalar(true) != Value::scalar(false));
    }

    #[test]
    fn array_equality() {
        let a = Value::Array(vec![Value::scalar("one"), Value::scalar("two")]);
        let b = Value::Array(vec![Value::scalar("alpha"), Value::scalar("beta")]);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn arrays_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Array(Vec::new()));
        assert!(Value::Array(Vec::new()).is_truthy());
    }

    #[test]
    fn object_equality() {
        let a: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
        ]
            .into_iter()
            .cloned()
            .collect();
        let a = Value::Object(a);

        let b: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
            ("gamma".into(), Value::Array(vec![])),
        ]
            .into_iter()
            .cloned()
            .collect();
        let b = Value::Object(b);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn objects_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Object(Object::new()));
        assert!(Value::Object(Object::new()).is_truthy());
    }

    #[test]
    fn nil_equality() {
        assert_eq!(Value::Nil, Value::Nil);
    }

    #[test]
    fn nils_have_ruby_truthiness() {
        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(!Value::Nil.is_truthy());

        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(Value::scalar(true) != Value::Nil);
        assert!(Value::scalar("") != Value::Nil);
    }
}
<|endoftext|>


<commit_before>use getopts::{optflag,usage,OptGroup};
use std::io::{println,print};

pub fn opts() -> [OptGroup, .. 2]{
    return [
        optflag("v", "version", "display the version"),
        optflag("h", "help", "print this help menu")
    ]
}

pub fn print_usage(_program: &str, opts: &[OptGroup]) {
    let space = "    ";
    println("Usage: muxed <command> [options]");
    println("");
    println("Commands:");
    println(format!("{}new [name]          create a new project file", space).as_slice());
    print(format!("{}open [name]         open a new project file", space).as_slice());
    println(usage("", opts).as_slice());
}
<commit_msg>Vanity test for opts. Allow dead code for print usage.<commit_after>use getopts::{optflag,usage,OptGroup};
use std::io::{println,print};

pub fn opts() -> [OptGroup, .. 2]{
    return [
        optflag("v", "version", "display the version"),
        optflag("h", "help", "print this help menu")
    ]
}

#[allow(dead_code)]
pub fn print_usage(_program: &str, opts: &[OptGroup]) {
    let space = "    ";
    println("Usage: muxed <command> [options]");
    println("");
    println("Commands:");
    println(format!("{}new [name]          create a new project file", space).as_slice());
    print(format!("{}open [name]         open a new project file", space).as_slice());
    println(usage("", opts).as_slice());
}

#[test]
fn opts_returns_two_options() {
  assert_eq!(opts().len(), 2);
}
<|endoftext|>


<commit_before>use sha2::{HashFunction, MAX_DIGEST_SIZE, Sha256, Sha384, Sha512};

const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c;

pub struct Hmac<T> {
    inner_hash_function: T,
    outer_hash_function: T,
}

macro_rules! impl_wrapper { ($function:ident, $key:expr, $message:expr) => {{
    let mut digest = [0; $function::DIGEST_SIZE];
    let mut hmac = Hmac::<$function>::new($key);
    hmac.update($message);
    hmac.write_digest(&mut digest);
    digest
}}}

pub fn hmac_sha512(key: &[u8], message: &[u8]) -> [u8; Sha512::DIGEST_SIZE] {
    impl_wrapper!(Sha512, key, message)
}

pub fn hmac_sha384(key: &[u8], message: &[u8]) -> [u8; Sha384::DIGEST_SIZE] {
    impl_wrapper!(Sha384, key, message)
}

pub fn hmac_sha256(key: &[u8], message: &[u8]) -> [u8; Sha256::DIGEST_SIZE] {
    impl_wrapper!(Sha256, key, message)
}

impl<T: HashFunction> Hmac<T> {
    pub fn new(key: &[u8]) -> Self {
        let mut hashed_key;
        let new_key;
        if key.len() > T::BLOCK_SIZE {
            hashed_key = [0; MAX_DIGEST_SIZE];
            let mut hash_function = T::default();
            hash_function.update(key);
            hash_function.write_digest(&mut hashed_key[..T::DIGEST_SIZE]);
            new_key = &hashed_key[..T::DIGEST_SIZE];
        } else {
            new_key = key;
        }
        Self {
            inner_hash_function: Self::keyed_hash_function(new_key, IPAD),
            outer_hash_function: Self::keyed_hash_function(new_key, OPAD),
        }
    }

    pub fn update(&mut self, input: &[u8]) {
        self.inner_hash_function.update(input);
    }

    pub fn write_digest(mut self, output: &mut [u8]) {
        self.inner_hash_function.write_digest(output);
        self.outer_hash_function.update(output);
        self.outer_hash_function.write_digest(output);
    }

    fn keyed_hash_function(key: &[u8], pad: u8) -> T {
        let mut hash_function = T::default();
        for byte in key {
            hash_function.update(&[byte ^ pad]);
        }
        for _ in key.len()..T::BLOCK_SIZE {
            hash_function.update(&[pad]);
        }
        hash_function
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test_helpers::*;

    fn check(exp512: &str, exp384: &str, exp256: &str, key: &[u8], data: &[u8]) {
        let expected = h2b(exp512);
        let mut actual = hmac_sha512(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha512>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());

        let expected = h2b(exp384);
        let mut actual = hmac_sha384(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha384>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());

        let expected = h2b(exp256);
        let mut actual = hmac_sha256(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha256>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());
    }

    #[test]
    fn test_digest() {
        let key = h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
        let data = b"Hi There";
        let exp512 = "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde\
                      daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854";
        let exp384 = "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c\
                      faea9ea9076ede7f4af152e8b2fa9cb6";
        let exp256 = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7";
        check(exp512, exp384, exp256, &key, data);

        let key = b"Jefe";
        let data = b"what do ya want for nothing?";
        let exp512 = "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554\
                      9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737";
        let exp384 = "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e\
                      8e2240ca5e69e2c78b3239ecfab21649";
        let exp256 = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
        check(exp512, exp384, exp256, key, data);

        let key = [0xaa; 20];
        let data = [0xdd; 50];
        let exp512 = "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39\
                      bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb";
        let exp384 = "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b\
                      2a5ab39dc13814b94e3ab6e101a34f27";
        let exp256 = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe";
        check(exp512, exp384, exp256, &key, &data);

        let key: Vec<_> = (0x01..0x1a).collect();
        let data = [0xcd; 50];
        let exp512 = "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db\
                      a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd";
        let exp384 = "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e\
                      6801dd23c4a7d679ccf8a386c674cffb";
        let exp256 = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b";
        check(exp512, exp384, exp256, &key, &data);

        let key = [0xaa; 131];
        let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
        let exp512 = "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352\
                      6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598";
        let exp384 = "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6\
                      0c2ef6ab4030fe8296248df163f44952";
        let exp256 = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54";
        check(exp512, exp384, exp256, &key, data);

        let data =
            b"This is a test using a larger than block-size key and a larger than block-\
              size data. The key needs to be hashed before being used by the HMAC algorithm.";
        let exp512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944\
                      b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58";
        let exp384 = "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5\
                      a678cc31e799176d3860e6110c46523e";
        let exp256 = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2";
        check(exp512, exp384, exp256, &key, data);
    }
}
<commit_msg>hmac: add sha-224<commit_after>use sha2::{HashFunction, MAX_DIGEST_SIZE, Sha224, Sha256, Sha384, Sha512};

const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c;

pub struct Hmac<T> {
    inner_hash_function: T,
    outer_hash_function: T,
}

macro_rules! impl_wrapper { ($function:ident, $key:expr, $message:expr) => {{
    let mut digest = [0; $function::DIGEST_SIZE];
    let mut hmac = Hmac::<$function>::new($key);
    hmac.update($message);
    hmac.write_digest(&mut digest);
    digest
}}}

pub fn hmac_sha512(key: &[u8], message: &[u8]) -> [u8; Sha512::DIGEST_SIZE] {
    impl_wrapper!(Sha512, key, message)
}

pub fn hmac_sha384(key: &[u8], message: &[u8]) -> [u8; Sha384::DIGEST_SIZE] {
    impl_wrapper!(Sha384, key, message)
}

pub fn hmac_sha256(key: &[u8], message: &[u8]) -> [u8; Sha256::DIGEST_SIZE] {
    impl_wrapper!(Sha256, key, message)
}

pub fn hmac_sha224(key: &[u8], message: &[u8]) -> [u8; Sha224::DIGEST_SIZE] {
    impl_wrapper!(Sha224, key, message)
}

impl<T: HashFunction> Hmac<T> {
    pub fn new(key: &[u8]) -> Self {
        let mut hashed_key;
        let new_key;
        if key.len() > T::BLOCK_SIZE {
            hashed_key = [0; MAX_DIGEST_SIZE];
            let mut hash_function = T::default();
            hash_function.update(key);
            hash_function.write_digest(&mut hashed_key[..T::DIGEST_SIZE]);
            new_key = &hashed_key[..T::DIGEST_SIZE];
        } else {
            new_key = key;
        }
        Self {
            inner_hash_function: Self::keyed_hash_function(new_key, IPAD),
            outer_hash_function: Self::keyed_hash_function(new_key, OPAD),
        }
    }

    pub fn update(&mut self, input: &[u8]) {
        self.inner_hash_function.update(input);
    }

    pub fn write_digest(mut self, output: &mut [u8]) {
        self.inner_hash_function.write_digest(output);
        self.outer_hash_function.update(output);
        self.outer_hash_function.write_digest(output);
    }

    fn keyed_hash_function(key: &[u8], pad: u8) -> T {
        let mut hash_function = T::default();
        for byte in key {
            hash_function.update(&[byte ^ pad]);
        }
        for _ in key.len()..T::BLOCK_SIZE {
            hash_function.update(&[pad]);
        }
        hash_function
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use test_helpers::*;

    fn check(exp512: &str, exp384: &str, exp256: &str, exp224: &str, key: &[u8], data: &[u8]) {
        let expected = h2b(exp512);
        let mut actual = hmac_sha512(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha512>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());

        let expected = h2b(exp384);
        let mut actual = hmac_sha384(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha384>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());

        let expected = h2b(exp256);
        let mut actual = hmac_sha256(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha256>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());

        let expected = h2b(exp224);
        let mut actual = hmac_sha224(key, data);
        assert_eq!(expected, actual.to_vec());

        let mut hmac = Hmac::<Sha224>::new(key);
        for word in data.chunks(4) {
            hmac.update(word);
        }
        hmac.write_digest(&mut actual);
        assert_eq!(expected, actual.to_vec());
    }

    #[test]
    fn test_digest() {
        let key = h2b("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
        let data = b"Hi There";
        let exp512 = "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde\
                      daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854";
        let exp384 = "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c\
                      faea9ea9076ede7f4af152e8b2fa9cb6";
        let exp256 = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7";
        let exp224 = "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22";
        check(exp512, exp384, exp256, exp224, &key, data);

        let key = b"Jefe";
        let data = b"what do ya want for nothing?";
        let exp512 = "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554\
                      9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737";
        let exp384 = "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e\
                      8e2240ca5e69e2c78b3239ecfab21649";
        let exp256 = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
        let exp224 = "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44";
        check(exp512, exp384, exp256, exp224, key, data);

        let key = [0xaa; 20];
        let data = [0xdd; 50];
        let exp512 = "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39\
                      bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb";
        let exp384 = "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b\
                      2a5ab39dc13814b94e3ab6e101a34f27";
        let exp256 = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe";
        let exp224 = "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea";
        check(exp512, exp384, exp256, exp224, &key, &data);

        let key: Vec<_> = (0x01..0x1a).collect();
        let data = [0xcd; 50];
        let exp512 = "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db\
                      a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd";
        let exp384 = "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e\
                      6801dd23c4a7d679ccf8a386c674cffb";
        let exp256 = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b";
        let exp224 = "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a";
        check(exp512, exp384, exp256, exp224, &key, &data);

        let key = [0xaa; 131];
        let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
        let exp512 = "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352\
                      6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598";
        let exp384 = "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6\
                      0c2ef6ab4030fe8296248df163f44952";
        let exp256 = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54";
        let exp224 = "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e";
        check(exp512, exp384, exp256, exp224, &key, data);

        let data =
            b"This is a test using a larger than block-size key and a larger than block-\
              size data. The key needs to be hashed before being used by the HMAC algorithm.";
        let exp512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944\
                      b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58";
        let exp384 = "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5\
                      a678cc31e799176d3860e6110c46523e";
        let exp256 = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2";
        let exp224 = "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1";
        check(exp512, exp384, exp256, exp224, &key, data);
    }
}
<|endoftext|>


<commit_before>/* diosix hypervisor code for handling hardware interrupts and software exceptions
 *
 * (c) Chris Williams, 2019-2020.
 *
 * See LICENSE for usage and copying.
 */

use super::scheduler;
use super::capsule;
use super::pcore;

/* platform-specific code must implement all this */
use platform;
use platform::irq::{IRQContext, IRQType, IRQCause, IRQ};
use platform::cpu::PrivilegeMode;

/* hypervisor_irq_handler
   entry point for hardware interrupts and software exceptions, collectively known as IRQs.
   call down into platform-specific handlers
   => context = platform-specific context of the IRQ
   <= returns flag word describing IRQ
*/
#[no_mangle]
pub extern "C" fn hypervisor_irq_handler(context: IRQContext)
{
    let irq = platform::irq::dispatch(context);
    match irq.irq_type
    {
        IRQType::Exception => exception(irq),
        IRQType::Interrupt => interrupt(irq),
    };
}

/* handle software exception */
fn exception(irq: IRQ)
{
    match (irq.fatal, irq.privilege_mode, irq.cause)
    {
        /* catch non-fatal supervisor-level exceptions */
        (false, PrivilegeMode::Supervisor, IRQCause::SupervisorEnvironmentCall) =>
        {
            if let Some(_c) = pcore::PhysicalCore::get_capsule_id()
            {
                hvdebug!("Environment call from supervisor-mode capsule ID {}", _c);
            }
            else
            {
                hvalert!("BUG: Environment call from supervisor mode but no capsule found");
            }
        },

        /* catch fatal supervisor-level exceptions */
        (true, PrivilegeMode::Supervisor, cause) =>
        {
            hvalert!(
                "Fatal exception in {:?}: {:?} at 0x{:x}, stack 0x{:x}",
                PrivilegeMode::Supervisor, cause, irq.pc, irq.sp);

            /* terminate the capsule running on this core */
            if let Some(c) = pcore::PhysicalCore::get_capsule_id()
            {
                if capsule::destroy(c).is_ok() != true
                {
                    hvalert!("BUG: Could not kill capsule ID {}", c);
                }
            }
            else
            {
                hvalert!("BUG: Exception in supervisor mode but no capsule found");
            }

            /* force a context switch */
            scheduler::run_next(true);
        },

        /* catch everything else, halting if fatal */
        (fatal, privilege, cause) =>
        {
            hvalert!("Unhandled exception in {:?}: {:?} at 0x{:x}, stack 0x{:x}, fatal = {:?}",
                privilege, cause, irq.pc, irq.sp, fatal);
            debughousekeeper!(); // flush the debug output

            /* stop here if we hit an unhandled fatal exception */
            if fatal == true
            {
                loop {}
            }
        }
    };
}

/* handle hardware interrupt */
fn interrupt(irq: IRQ)
{
    match irq.cause
    {
        /* handle our scheduler's timer by picking another thing to run, if possible */
        IRQCause::HypervisorTimer => scheduler::run_next(false),
        _ => hvdebug!("Unhandled hardware interrupt: {:?}", irq.cause)
    };

    /* clear the interrupt condition */
    platform::irq::acknowledge(irq);
}
<commit_msg>Halt supervisor on unhandled exception<commit_after>/* diosix hypervisor code for handling hardware interrupts and software exceptions
 *
 * (c) Chris Williams, 2019-2020.
 *
 * See LICENSE for usage and copying.
 */

use super::scheduler;
use super::capsule;
use super::pcore;

/* platform-specific code must implement all this */
use platform;
use platform::irq::{IRQContext, IRQType, IRQCause, IRQ};
use platform::cpu::PrivilegeMode;

/* hypervisor_irq_handler
   entry point for hardware interrupts and software exceptions, collectively known as IRQs.
   call down into platform-specific handlers
   => context = platform-specific context of the IRQ
   <= returns flag word describing IRQ
*/
#[no_mangle]
pub extern "C" fn hypervisor_irq_handler(context: IRQContext)
{
    let irq = platform::irq::dispatch(context);
    match irq.irq_type
    {
        IRQType::Exception => exception(irq),
        IRQType::Interrupt => interrupt(irq),
    };
}

/* handle software exception */
fn exception(irq: IRQ)
{
    match (irq.fatal, irq.privilege_mode, irq.cause)
    {
        /* catch non-fatal supervisor-level exceptions */
        (false, PrivilegeMode::Supervisor, IRQCause::SupervisorEnvironmentCall) =>
        {
            if let Some(_c) = pcore::PhysicalCore::get_capsule_id()
            {
                hvdebug!("Environment call from supervisor-mode capsule ID {}", _c);
            }
            else
            {
                hvalert!("BUG: Environment call from supervisor mode but no capsule found");
            }
        },

        /* catch fatal supervisor-level exceptions */
        (true, PrivilegeMode::Supervisor, cause) =>
        {
            hvalert!(
                "Fatal exception in {:?}: {:?} at 0x{:x}, stack 0x{:x}",
                PrivilegeMode::Supervisor, cause, irq.pc, irq.sp);

            /* terminate the capsule running on this core */
            if let Some(c) = pcore::PhysicalCore::get_capsule_id()
            {
                if capsule::destroy(c).is_ok() != true
                {
                    hvalert!("BUG: Could not kill capsule ID {}", c);
                }
            }
            else
            {
                hvalert!("BUG: Exception in supervisor mode but no capsule found");
            }

            /* force a context switch */
            scheduler::run_next(true);
        },

        /* catch everything else, halting if fatal */
        (fatal, privilege, cause) =>
        {
            hvalert!("Unhandled exception in {:?}: {:?} at 0x{:x}, stack 0x{:x}, fatal = {:?}",
                privilege, cause, irq.pc, irq.sp, fatal);
            debughousekeeper!(); // flush the debug output

            /* stop here if we hit an unhandled fatal exception */
            // if fatal == true
            {
                loop {}
            }
        }
    };
}

/* handle hardware interrupt */
fn interrupt(irq: IRQ)
{
    match irq.cause
    {
        /* handle our scheduler's timer by picking another thing to run, if possible */
        IRQCause::HypervisorTimer => scheduler::run_next(false),
        _ => hvdebug!("Unhandled hardware interrupt: {:?}", irq.cause)
    };

    /* clear the interrupt condition */
    platform::irq::acknowledge(irq);
}
<|endoftext|>


<commit_before>use std::cmp;
use std::fmt;
use std::net::Ipv6Addr;
use std::str::FromStr;

use common::{IpNetworkError, cidr_parts, parse_prefix};

const IPV6_BITS: u8 = 128;
const IPV6_SEGMENT_BITS: u8 = 16;

#[derive(Debug,Clone,Copy,Hash,PartialEq,Eq)]
pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv6Network {
    /// Constructs a new `Ipv6Network` from any `Ipv6Addr` and a prefix denoting the network size.
    /// If the prefix is larger than 128 this will return an `IpNetworkError::InvalidPrefix`.
    pub fn new(addr: Ipv6Addr, prefix: u8) -> Result<Ipv6Network, IpNetworkError> {
        if prefix > IPV6_BITS {
            Err(IpNetworkError::InvalidPrefix)
        } else {
            Ok(Ipv6Network {
                addr: addr,
                prefix: prefix,
            })
        }
    }

    pub fn from_cidr(cidr: &str) -> Result<Ipv6Network, IpNetworkError> {
        let (addr_str, prefix_str) = try!(cidr_parts(cidr));
        let addr = try!(Ipv6Addr::from_str(addr_str)
            .map_err(|_| IpNetworkError::InvalidAddr(format!("{}", addr_str))));
        let prefix = try!(parse_prefix(prefix_str, IPV6_BITS));
        Self::new(addr, prefix)
    }

    pub fn ip(&self) -> Ipv6Addr {
        self.addr
    }

    pub fn prefix(&self) -> u8 {
        self.prefix
    }

    /// Returns the mask for this `Ipv6Network`.
    /// That means the `prefix` most significant bits will be 1 and the rest 0
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv6Addr;
    /// use ipnetwork::Ipv6Network;
    ///
    /// let net = Ipv6Network::from_cidr("ff01::0/32").unwrap();
    /// assert_eq!(net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn mask(&self) -> Ipv6Addr {
        // Ipv6Addr::from is only implemented for [u8; 16]
        let mut segments = [0; 16];
        for (i, segment) in segments.iter_mut().enumerate() {
            let bits_remaining = self.prefix.saturating_sub(i as u8 * 8);
            let set_bits = cmp::min(bits_remaining, 8);
            *segment = !(0xff as u16 >> set_bits) as u8;
        }
        Ipv6Addr::from(segments)
    }

    /// Checks if a given `Ipv6Addr` is in this `Ipv6Network`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv6Addr;
    /// use ipnetwork::Ipv6Network;
    ///
    /// let net = Ipv6Network::from_cidr("ff01::0/32").unwrap();
    /// assert!(net.contains(Ipv6Addr::new(0xff01, 0, 0, 0, 0, 0, 0, 0x1)));
    /// assert!(!net.contains(Ipv6Addr::new(0xffff, 0, 0, 0, 0, 0, 0, 0x1)));
    /// ```
    pub fn contains(&self, ip: Ipv6Addr) -> bool {
        let a = self.addr.segments();
        let b = ip.segments();
        let addrs = Iterator::zip(a.iter(), b.iter());
        self.mask().segments().iter().zip(addrs).all(|(mask, (a, b))|
            a & mask == b & mask
        )
    }
}

impl fmt::Display for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

/// Converts a `Ipv6Addr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, IpNetworkError> {
    let mask = mask.segments();
    let mut mask_iter = mask.into_iter();

    // Count the number of set bits from the start of the address
    let mut prefix = 0;
    for &segment in &mut mask_iter {
        if segment == 0xffff {
            prefix += IPV6_SEGMENT_BITS;
        } else if segment == 0 {
            // Prefix finishes on a segment boundary
            break;
        } else {
            let prefix_bits = (!segment).leading_zeros() as u8;
            // Check that the remainder of the bits are all unset
            if segment << prefix_bits != 0 {
                return Err(IpNetworkError::InvalidPrefix);
            }
            prefix += prefix_bits;
            break;
        }
    }

    // Now check all the remaining bits are unset
    for &segment in mask_iter {
        if segment != 0 {
            return Err(IpNetworkError::InvalidPrefix);
        }
    }

    Ok(prefix)
}

#[cfg(test)]
mod test {
    use std::net::Ipv6Addr;
    use super::*;

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24).unwrap();
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6_invalid_prefix() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 129);
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v6() {
        let cidr = Ipv6Network::from_cidr("::1/0").unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
        assert_eq!(cidr.prefix(), 0);
    }

    #[test]
    fn parse_v6_2() {
        let cidr = Ipv6Network::from_cidr("FF01:0:0:17:0:0:0:2/64").unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2));
        assert_eq!(cidr.prefix(), 64);
    }

    #[test]
    fn parse_v6_fail_addr() {
        let cidr = Ipv6Network::from_cidr("2001::1::/8");
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v6_fail_prefix() {
        let cidr = Ipv6Network::from_cidr("::1/129");
        assert!(cidr.is_err());
    }

    #[test]
    fn mask_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 40).unwrap();
        let mask = cidr.mask();
        assert_eq!(mask, Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0));
    }

    #[test]
    fn contains_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 65).unwrap();
        let ip = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0x7fff, 0, 0, 0x2);
        assert!(cidr.contains(ip));
    }

    #[test]
    fn not_contains_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 65).unwrap();
        let ip = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0xffff, 0, 0, 0x2);
        assert!(!cidr.contains(ip));
    }

    #[test]
    fn v6_mask_to_prefix() {
        let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
        let prefix = ipv6_mask_to_prefix(mask).unwrap();
        assert_eq!(prefix, 48);
    }

    #[test]
    fn invalid_v6_mask_to_prefix() {
        let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
        let prefix = ipv6_mask_to_prefix(mask);
        assert!(prefix.is_err());
    }
}
<commit_msg>Implement FromStr for IPv6<commit_after>use std::cmp;
use std::fmt;
use std::net::Ipv6Addr;
use std::str::FromStr;

use common::{IpNetworkError, cidr_parts, parse_prefix};

const IPV6_BITS: u8 = 128;
const IPV6_SEGMENT_BITS: u8 = 16;

#[derive(Debug,Clone,Copy,Hash,PartialEq,Eq)]
pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv6Network {
    /// Constructs a new `Ipv6Network` from any `Ipv6Addr` and a prefix denoting the network size.
    /// If the prefix is larger than 128 this will return an `IpNetworkError::InvalidPrefix`.
    pub fn new(addr: Ipv6Addr, prefix: u8) -> Result<Ipv6Network, IpNetworkError> {
        if prefix > IPV6_BITS {
            Err(IpNetworkError::InvalidPrefix)
        } else {
            Ok(Ipv6Network {
                addr: addr,
                prefix: prefix,
            })
        }
    }

    #[deprecated(since="0.9.1", note="please use `String::parse()` instead")]
    fn from_cidr(cidr: &str) -> Result<Ipv6Network, IpNetworkError> {
        cidr.parse()
    }

    pub fn ip(&self) -> Ipv6Addr {
        self.addr
    }

    pub fn prefix(&self) -> u8 {
        self.prefix
    }

    /// Returns the mask for this `Ipv6Network`.
    /// That means the `prefix` most significant bits will be 1 and the rest 0
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv6Addr;
    /// use ipnetwork::Ipv6Network;
    ///
    /// let net: Ipv6Network = "ff01::0/32".parse().unwrap();
    /// assert_eq!(net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
    /// ```
    pub fn mask(&self) -> Ipv6Addr {
        // Ipv6Addr::from is only implemented for [u8; 16]
        let mut segments = [0; 16];
        for (i, segment) in segments.iter_mut().enumerate() {
            let bits_remaining = self.prefix.saturating_sub(i as u8 * 8);
            let set_bits = cmp::min(bits_remaining, 8);
            *segment = !(0xff as u16 >> set_bits) as u8;
        }
        Ipv6Addr::from(segments)
    }

    /// Checks if a given `Ipv6Addr` is in this `Ipv6Network`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv6Addr;
    /// use ipnetwork::Ipv6Network;
    ///
    /// let net: Ipv6Network = "ff01::0/32".parse().unwrap();
    /// assert!(net.contains(Ipv6Addr::new(0xff01, 0, 0, 0, 0, 0, 0, 0x1)));
    /// assert!(!net.contains(Ipv6Addr::new(0xffff, 0, 0, 0, 0, 0, 0, 0x1)));
    /// ```
    pub fn contains(&self, ip: Ipv6Addr) -> bool {
        let a = self.addr.segments();
        let b = ip.segments();
        let addrs = Iterator::zip(a.iter(), b.iter());
        self.mask().segments().iter().zip(addrs).all(|(mask, (a, b))| a & mask == b & mask)
    }
}

impl FromStr for Ipv6Network {
    type Err = IpNetworkError;
    fn from_str(s: &str) -> Result<Ipv6Network, IpNetworkError> {
        let (addr_str, prefix_str) = try!(cidr_parts(s));
        let addr = try!(Ipv6Addr::from_str(addr_str)
            .map_err(|_| IpNetworkError::InvalidAddr(format!("{}", addr_str))));
        let prefix = try!(parse_prefix(prefix_str, IPV6_BITS));
        Ipv6Network::new(addr, prefix)
    }
}

impl fmt::Display for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

/// Converts a `Ipv6Addr` network mask into a prefix.
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, IpNetworkError> {
    let mask = mask.segments();
    let mut mask_iter = mask.into_iter();

    // Count the number of set bits from the start of the address
    let mut prefix = 0;
    for &segment in &mut mask_iter {
        if segment == 0xffff {
            prefix += IPV6_SEGMENT_BITS;
        } else if segment == 0 {
            // Prefix finishes on a segment boundary
            break;
        } else {
            let prefix_bits = (!segment).leading_zeros() as u8;
            // Check that the remainder of the bits are all unset
            if segment << prefix_bits != 0 {
                return Err(IpNetworkError::InvalidPrefix);
            }
            prefix += prefix_bits;
            break;
        }
    }

    // Now check all the remaining bits are unset
    for &segment in mask_iter {
        if segment != 0 {
            return Err(IpNetworkError::InvalidPrefix);
        }
    }

    Ok(prefix)
}

#[cfg(test)]
mod test {
    use std::net::Ipv6Addr;
    use super::*;

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24).unwrap();
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6_invalid_prefix() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 129);
        assert!(cidr.is_err());
    }

    #[test]
    fn parse_v6() {
        let cidr: Ipv6Network = "::1/0".parse().unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
        assert_eq!(cidr.prefix(), 0);
    }

    #[test]
    fn parse_v6_2() {
        let cidr: Ipv6Network = "FF01:0:0:17:0:0:0:2/64".parse().unwrap();
        assert_eq!(cidr.ip(), Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2));
        assert_eq!(cidr.prefix(), 64);
    }

    #[test]
    fn parse_v6_fail_addr() {
        let cidr: Option<Ipv6Network> = "2001::1::/8".parse().ok();
        assert_eq!(None, cidr);
    }

    #[test]
    fn parse_v6_fail_prefix() {
        let cidr: Option<Ipv6Network> = "::1/129".parse().ok();
        assert_eq!(None, cidr);
    }

    #[test]
    fn mask_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 40).unwrap();
        let mask = cidr.mask();
        assert_eq!(mask, Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0));
    }

    #[test]
    fn contains_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 65).unwrap();
        let ip = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0x7fff, 0, 0, 0x2);
        assert!(cidr.contains(ip));
    }

    #[test]
    fn not_contains_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 65).unwrap();
        let ip = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0xffff, 0, 0, 0x2);
        assert!(!cidr.contains(ip));
    }

    #[test]
    fn v6_mask_to_prefix() {
        let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
        let prefix = ipv6_mask_to_prefix(mask).unwrap();
        assert_eq!(prefix, 48);
    }

    #[test]
    fn invalid_v6_mask_to_prefix() {
        let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
        let prefix = ipv6_mask_to_prefix(mask);
        assert!(prefix.is_err());
    }
}
<|endoftext|>


<commit_before>use proc_macro2::{Ident, Span};
use std::fmt;

/// Specialized formatting trait used by `format_ident!`.
///
/// [`Ident`] arguments formatted using this trait will have their `r#` prefix
/// stripped, if present.
///
/// See [`format_ident!`] for more information.
pub trait IdentFragment {
    /// Format this value as an identifier fragment.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;

    /// Span associated with this `IdentFragment`.
    ///
    /// If non-`None`, may be inherited by formatted identifiers.
    fn span(&self) -> Option<Span> {
        None
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &mut T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl IdentFragment for Ident {
    fn span(&self) -> Option<Span> {
        Some(self.span())
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let id = self.to_string();
        if id.starts_with("r#") {
            fmt::Display::fmt(&id[2..], f)
        } else {
            fmt::Display::fmt(&id[..], f)
        }
    }
}

impl<'a, T> IdentFragment for std::borrow::Cow<'a, T>
where
    T: 'a + IdentFragment + ToOwned + ?Sized,
{
    fn span(&self) -> Option<Span> {
        T::span(&self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        T::fmt(&self, f)
    }
}

// Limited set of types which this is implemented for, as we want to avoid types
// which will often include non-identifier characters in their `Display` impl.
macro_rules! ident_fragment_display {
    ($($T:ty),*) => {
        $(
            impl IdentFragment for $T {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Display::fmt(self, f)
                }
            }
        )*
    }
}

ident_fragment_display!(bool, str, String, char);
ident_fragment_display!(u8, u16, u32, u64, u128, usize);
<commit_msg>Touch up PR 158<commit_after>use proc_macro2::{Ident, Span};
use std::borrow::Cow;
use std::fmt;

/// Specialized formatting trait used by `format_ident!`.
///
/// [`Ident`] arguments formatted using this trait will have their `r#` prefix
/// stripped, if present.
///
/// See [`format_ident!`] for more information.
pub trait IdentFragment {
    /// Format this value as an identifier fragment.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;

    /// Span associated with this `IdentFragment`.
    ///
    /// If non-`None`, may be inherited by formatted identifiers.
    fn span(&self) -> Option<Span> {
        None
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl<T: IdentFragment + ?Sized> IdentFragment for &mut T {
    fn span(&self) -> Option<Span> {
        <T as IdentFragment>::span(*self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        IdentFragment::fmt(*self, f)
    }
}

impl IdentFragment for Ident {
    fn span(&self) -> Option<Span> {
        Some(self.span())
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let id = self.to_string();
        if id.starts_with("r#") {
            fmt::Display::fmt(&id[2..], f)
        } else {
            fmt::Display::fmt(&id[..], f)
        }
    }
}

impl<T> IdentFragment for Cow<'_, T>
where
    T: IdentFragment + ToOwned + ?Sized,
{
    fn span(&self) -> Option<Span> {
        T::span(self)
    }

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        T::fmt(self, f)
    }
}

// Limited set of types which this is implemented for, as we want to avoid types
// which will often include non-identifier characters in their `Display` impl.
macro_rules! ident_fragment_display {
    ($($T:ty),*) => {
        $(
            impl IdentFragment for $T {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Display::fmt(self, f)
                }
            }
        )*
    }
}

ident_fragment_display!(bool, str, String, char);
ident_fragment_display!(u8, u16, u32, u64, u128, usize);
<|endoftext|>


<commit_before>use std::str::FromStr;

use crate::array_of_tables::ArrayOfTables;
use crate::datetime::*;
use crate::table::TableLike;
use crate::{Array, InlineTable, Table, Value};

/// Type representing either a value, a table, an array of tables, or none.
#[derive(Debug, Clone)]
pub enum Item {
    /// Type representing none.
    None,
    /// Type representing value.
    Value(Value),
    /// Type representing table.
    Table(Table),
    /// Type representing array of tables.
    ArrayOfTables(ArrayOfTables),
}

impl Item {
    /// Sets `self` to the given item iff `self` is none and
    /// returns a mutable reference to `self`.
    pub fn or_insert(&mut self, item: Item) -> &mut Item {
        if self.is_none() {
            *self = item
        }
        self
    }
}

// TODO: This should be generated by macro or derive
/// Downcasting
impl Item {
    /// Text description of value type
    pub fn type_name(&self) -> &'static str {
        match self {
            Item::None => "none",
            Item::Value(v) => v.type_name(),
            Item::Table(..) => "table",
            Item::ArrayOfTables(..) => "array of tables",
        }
    }

    /// Index into a TOML array or map. A string index can be used to access a
    /// value in a map, and a usize index can be used to access an element of an
    /// array.
    ///
    /// Returns `None` if:
    /// - The type of `self` does not match the type of the
    ///   index, for example if the index is a string and `self` is an array or a
    ///   number.
    /// - The given key does not exist in the map
    ///   or the given index is not within the bounds of the array.
    pub fn get<I: crate::index::Index>(&self, index: I) -> Option<&Item> {
        index.index(self)
    }

    /// Mutably index into a TOML array or map. A string index can be used to
    /// access a value in a map, and a usize index can be used to access an
    /// element of an array.
    ///
    /// Returns `None` if:
    /// - The type of `self` does not match the type of the
    ///   index, for example if the index is a string and `self` is an array or a
    ///   number.
    /// - The given key does not exist in the map
    ///   or the given index is not within the bounds of the array.
    pub fn get_mut<I: crate::index::Index>(&mut self, index: I) -> Option<&mut Item> {
        index.index_mut(self)
    }

    /// Casts `self` to value.
    pub fn as_value(&self) -> Option<&Value> {
        match *self {
            Item::Value(ref v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to table.
    pub fn as_table(&self) -> Option<&Table> {
        match *self {
            Item::Table(ref t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to array of tables.
    pub fn as_array_of_tables(&self) -> Option<&ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref a) => Some(a),
            _ => None,
        }
    }
    /// Casts `self` to mutable value.
    pub fn as_value_mut(&mut self) -> Option<&mut Value> {
        match *self {
            Item::Value(ref mut v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to mutable table.
    pub fn as_table_mut(&mut self) -> Option<&mut Table> {
        match *self {
            Item::Table(ref mut t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to mutable array of tables.
    pub fn as_array_of_tables_mut(&mut self) -> Option<&mut ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref mut a) => Some(a),
            _ => None,
        }
    }
    /// Casts `self` to value.
    pub fn into_value(self) -> Result<Value, Self> {
        match self {
            Item::None => Err(self),
            Item::Value(v) => Ok(v),
            Item::Table(v) => {
                let v = v.into_inline_table();
                Ok(Value::InlineTable(v))
            }
            Item::ArrayOfTables(v) => {
                let v = v.into_array();
                Ok(Value::Array(v))
            }
        }
    }
    /// In-place convert to a value
    pub fn make_value(&mut self) {
        let other = std::mem::take(self);
        let other = other.into_value().map(Item::Value).unwrap_or(Item::None);
        *self = other;
    }
    /// Casts `self` to table.
    pub fn into_table(self) -> Result<Table, Self> {
        match self {
            Item::Table(t) => Ok(t),
            Item::Value(Value::InlineTable(t)) => Ok(t.into_table()),
            _ => Err(self),
        }
    }
    /// Casts `self` to array of tables.
    pub fn into_array_of_tables(self) -> Result<ArrayOfTables, Self> {
        match self {
            Item::ArrayOfTables(a) => Ok(a),
            Item::Value(Value::Array(a)) => {
                if a.is_empty() {
                    Err(Item::Value(Value::Array(a)))
                } else if a.iter().all(|v| v.is_inline_table()) {
                    let mut aot = ArrayOfTables::new();
                    aot.values = a.values;
                    for value in aot.values.iter_mut() {
                        value.make_item();
                    }
                    Ok(aot)
                } else {
                    Err(Item::Value(Value::Array(a)))
                }
            }
            _ => Err(self),
        }
    }
    // Starting private because the name is unclear
    pub(crate) fn make_item(&mut self) {
        let other = std::mem::take(self);
        let other = match other.into_table().map(crate::Item::Table) {
            Ok(i) => i,
            Err(i) => i,
        };
        let other = match other.into_array_of_tables().map(crate::Item::ArrayOfTables) {
            Ok(i) => i,
            Err(i) => i,
        };
        *self = other;
    }
    /// Returns true iff `self` is a value.
    pub fn is_value(&self) -> bool {
        self.as_value().is_some()
    }
    /// Returns true iff `self` is a table.
    pub fn is_table(&self) -> bool {
        self.as_table().is_some()
    }
    /// Returns true iff `self` is an array of tables.
    pub fn is_array_of_tables(&self) -> bool {
        self.as_array_of_tables().is_some()
    }
    /// Returns true iff `self` is `None`.
    pub fn is_none(&self) -> bool {
        matches!(*self, Item::None)
    }

    // Duplicate Value downcasting API

    /// Casts `self` to integer.
    pub fn as_integer(&self) -> Option<i64> {
        self.as_value().and_then(Value::as_integer)
    }

    /// Returns true iff `self` is an integer.
    pub fn is_integer(&self) -> bool {
        self.as_integer().is_some()
    }

    /// Casts `self` to float.
    pub fn as_float(&self) -> Option<f64> {
        self.as_value().and_then(Value::as_float)
    }

    /// Returns true iff `self` is a float.
    pub fn is_float(&self) -> bool {
        self.as_float().is_some()
    }

    /// Casts `self` to boolean.
    pub fn as_bool(&self) -> Option<bool> {
        self.as_value().and_then(Value::as_bool)
    }

    /// Returns true iff `self` is a boolean.
    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    /// Casts `self` to str.
    pub fn as_str(&self) -> Option<&str> {
        self.as_value().and_then(Value::as_str)
    }

    /// Returns true iff `self` is a string.
    pub fn is_str(&self) -> bool {
        self.as_str().is_some()
    }

    /// Casts `self` to date-time.
    pub fn as_datetime(&self) -> Option<&Datetime> {
        self.as_value().and_then(Value::as_datetime)
    }

    /// Returns true iff `self` is a date-time.
    pub fn is_datetime(&self) -> bool {
        self.as_datetime().is_some()
    }

    /// Casts `self` to array.
    pub fn as_array(&self) -> Option<&Array> {
        self.as_value().and_then(Value::as_array)
    }

    /// Casts `self` to mutable array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        self.as_value_mut().and_then(Value::as_array_mut)
    }

    /// Returns true iff `self` is an array.
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Casts `self` to inline table.
    pub fn as_inline_table(&self) -> Option<&InlineTable> {
        self.as_value().and_then(Value::as_inline_table)
    }

    /// Casts `self` to mutable inline table.
    pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
        self.as_value_mut().and_then(Value::as_inline_table_mut)
    }

    /// Returns true iff `self` is an inline table.
    pub fn is_inline_table(&self) -> bool {
        self.as_inline_table().is_some()
    }

    /// Casts `self` to either a table or an inline table.
    pub fn as_table_like(&self) -> Option<&dyn TableLike> {
        self.as_table()
            .map(|t| t as &dyn TableLike)
            .or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike))
    }

    /// Casts `self` to either a table or an inline table.
    pub fn as_table_like_mut(&mut self) -> Option<&mut dyn TableLike> {
        match self {
            Item::Table(t) => Some(t as &mut dyn TableLike),
            Item::Value(Value::InlineTable(t)) => Some(t as &mut dyn TableLike),
            _ => None,
        }
    }

    /// Returns true iff `self` is either a table, or an inline table.
    pub fn is_table_like(&self) -> bool {
        self.as_table_like().is_some()
    }
}

impl Default for Item {
    fn default() -> Self {
        Item::None
    }
}

impl FromStr for Item {
    type Err = crate::TomlError;

    /// Parses a value from a &str
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let value = s.parse::<Value>()?;
        Ok(Item::Value(value))
    }
}

impl std::fmt::Display for Item {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match &self {
            Item::None => Ok(()),
            Item::Value(v) => v.fmt(f),
            Item::Table(v) => v.fmt(f),
            Item::ArrayOfTables(v) => v.fmt(f),
        }
    }
}

/// Returns a formatted value.
///
/// Since formatting is part of a `Value`, the right hand side of the
/// assignment needs to be decorated with a space before the value.
/// The `value` function does just that.
///
/// # Examples
/// ```rust
/// # use pretty_assertions::assert_eq;
/// # use toml_edit::*;
/// let mut table = Table::default();
/// let mut array = Array::default();
/// array.push("hello");
/// array.push("\\, world"); // \ is only allowed in a literal string
/// table["key1"] = value("value1");
/// table["key2"] = value(42);
/// table["key3"] = value(array);
/// assert_eq!(table.to_string(),
/// r#"key1 = "value1"
/// key2 = 42
/// key3 = ["hello", '\, world']
/// "#);
/// ```
pub fn value<V: Into<Value>>(v: V) -> Item {
    Item::Value(v.into().decorated(" ", ""))
}

/// Returns an empty table.
pub fn table() -> Item {
    Item::Table(Table::new())
}

/// Returns an empty array of tables.
pub fn array() -> Item {
    Item::ArrayOfTables(ArrayOfTables::new())
}
<commit_msg>fix: toml_edit::value uses default decor<commit_after>use std::str::FromStr;

use crate::array_of_tables::ArrayOfTables;
use crate::datetime::*;
use crate::table::TableLike;
use crate::{Array, InlineTable, Table, Value};

/// Type representing either a value, a table, an array of tables, or none.
#[derive(Debug, Clone)]
pub enum Item {
    /// Type representing none.
    None,
    /// Type representing value.
    Value(Value),
    /// Type representing table.
    Table(Table),
    /// Type representing array of tables.
    ArrayOfTables(ArrayOfTables),
}

impl Item {
    /// Sets `self` to the given item iff `self` is none and
    /// returns a mutable reference to `self`.
    pub fn or_insert(&mut self, item: Item) -> &mut Item {
        if self.is_none() {
            *self = item
        }
        self
    }
}

// TODO: This should be generated by macro or derive
/// Downcasting
impl Item {
    /// Text description of value type
    pub fn type_name(&self) -> &'static str {
        match self {
            Item::None => "none",
            Item::Value(v) => v.type_name(),
            Item::Table(..) => "table",
            Item::ArrayOfTables(..) => "array of tables",
        }
    }

    /// Index into a TOML array or map. A string index can be used to access a
    /// value in a map, and a usize index can be used to access an element of an
    /// array.
    ///
    /// Returns `None` if:
    /// - The type of `self` does not match the type of the
    ///   index, for example if the index is a string and `self` is an array or a
    ///   number.
    /// - The given key does not exist in the map
    ///   or the given index is not within the bounds of the array.
    pub fn get<I: crate::index::Index>(&self, index: I) -> Option<&Item> {
        index.index(self)
    }

    /// Mutably index into a TOML array or map. A string index can be used to
    /// access a value in a map, and a usize index can be used to access an
    /// element of an array.
    ///
    /// Returns `None` if:
    /// - The type of `self` does not match the type of the
    ///   index, for example if the index is a string and `self` is an array or a
    ///   number.
    /// - The given key does not exist in the map
    ///   or the given index is not within the bounds of the array.
    pub fn get_mut<I: crate::index::Index>(&mut self, index: I) -> Option<&mut Item> {
        index.index_mut(self)
    }

    /// Casts `self` to value.
    pub fn as_value(&self) -> Option<&Value> {
        match *self {
            Item::Value(ref v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to table.
    pub fn as_table(&self) -> Option<&Table> {
        match *self {
            Item::Table(ref t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to array of tables.
    pub fn as_array_of_tables(&self) -> Option<&ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref a) => Some(a),
            _ => None,
        }
    }
    /// Casts `self` to mutable value.
    pub fn as_value_mut(&mut self) -> Option<&mut Value> {
        match *self {
            Item::Value(ref mut v) => Some(v),
            _ => None,
        }
    }
    /// Casts `self` to mutable table.
    pub fn as_table_mut(&mut self) -> Option<&mut Table> {
        match *self {
            Item::Table(ref mut t) => Some(t),
            _ => None,
        }
    }
    /// Casts `self` to mutable array of tables.
    pub fn as_array_of_tables_mut(&mut self) -> Option<&mut ArrayOfTables> {
        match *self {
            Item::ArrayOfTables(ref mut a) => Some(a),
            _ => None,
        }
    }
    /// Casts `self` to value.
    pub fn into_value(self) -> Result<Value, Self> {
        match self {
            Item::None => Err(self),
            Item::Value(v) => Ok(v),
            Item::Table(v) => {
                let v = v.into_inline_table();
                Ok(Value::InlineTable(v))
            }
            Item::ArrayOfTables(v) => {
                let v = v.into_array();
                Ok(Value::Array(v))
            }
        }
    }
    /// In-place convert to a value
    pub fn make_value(&mut self) {
        let other = std::mem::take(self);
        let other = other.into_value().map(Item::Value).unwrap_or(Item::None);
        *self = other;
    }
    /// Casts `self` to table.
    pub fn into_table(self) -> Result<Table, Self> {
        match self {
            Item::Table(t) => Ok(t),
            Item::Value(Value::InlineTable(t)) => Ok(t.into_table()),
            _ => Err(self),
        }
    }
    /// Casts `self` to array of tables.
    pub fn into_array_of_tables(self) -> Result<ArrayOfTables, Self> {
        match self {
            Item::ArrayOfTables(a) => Ok(a),
            Item::Value(Value::Array(a)) => {
                if a.is_empty() {
                    Err(Item::Value(Value::Array(a)))
                } else if a.iter().all(|v| v.is_inline_table()) {
                    let mut aot = ArrayOfTables::new();
                    aot.values = a.values;
                    for value in aot.values.iter_mut() {
                        value.make_item();
                    }
                    Ok(aot)
                } else {
                    Err(Item::Value(Value::Array(a)))
                }
            }
            _ => Err(self),
        }
    }
    // Starting private because the name is unclear
    pub(crate) fn make_item(&mut self) {
        let other = std::mem::take(self);
        let other = match other.into_table().map(crate::Item::Table) {
            Ok(i) => i,
            Err(i) => i,
        };
        let other = match other.into_array_of_tables().map(crate::Item::ArrayOfTables) {
            Ok(i) => i,
            Err(i) => i,
        };
        *self = other;
    }
    /// Returns true iff `self` is a value.
    pub fn is_value(&self) -> bool {
        self.as_value().is_some()
    }
    /// Returns true iff `self` is a table.
    pub fn is_table(&self) -> bool {
        self.as_table().is_some()
    }
    /// Returns true iff `self` is an array of tables.
    pub fn is_array_of_tables(&self) -> bool {
        self.as_array_of_tables().is_some()
    }
    /// Returns true iff `self` is `None`.
    pub fn is_none(&self) -> bool {
        matches!(*self, Item::None)
    }

    // Duplicate Value downcasting API

    /// Casts `self` to integer.
    pub fn as_integer(&self) -> Option<i64> {
        self.as_value().and_then(Value::as_integer)
    }

    /// Returns true iff `self` is an integer.
    pub fn is_integer(&self) -> bool {
        self.as_integer().is_some()
    }

    /// Casts `self` to float.
    pub fn as_float(&self) -> Option<f64> {
        self.as_value().and_then(Value::as_float)
    }

    /// Returns true iff `self` is a float.
    pub fn is_float(&self) -> bool {
        self.as_float().is_some()
    }

    /// Casts `self` to boolean.
    pub fn as_bool(&self) -> Option<bool> {
        self.as_value().and_then(Value::as_bool)
    }

    /// Returns true iff `self` is a boolean.
    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    /// Casts `self` to str.
    pub fn as_str(&self) -> Option<&str> {
        self.as_value().and_then(Value::as_str)
    }

    /// Returns true iff `self` is a string.
    pub fn is_str(&self) -> bool {
        self.as_str().is_some()
    }

    /// Casts `self` to date-time.
    pub fn as_datetime(&self) -> Option<&Datetime> {
        self.as_value().and_then(Value::as_datetime)
    }

    /// Returns true iff `self` is a date-time.
    pub fn is_datetime(&self) -> bool {
        self.as_datetime().is_some()
    }

    /// Casts `self` to array.
    pub fn as_array(&self) -> Option<&Array> {
        self.as_value().and_then(Value::as_array)
    }

    /// Casts `self` to mutable array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        self.as_value_mut().and_then(Value::as_array_mut)
    }

    /// Returns true iff `self` is an array.
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Casts `self` to inline table.
    pub fn as_inline_table(&self) -> Option<&InlineTable> {
        self.as_value().and_then(Value::as_inline_table)
    }

    /// Casts `self` to mutable inline table.
    pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> {
        self.as_value_mut().and_then(Value::as_inline_table_mut)
    }

    /// Returns true iff `self` is an inline table.
    pub fn is_inline_table(&self) -> bool {
        self.as_inline_table().is_some()
    }

    /// Casts `self` to either a table or an inline table.
    pub fn as_table_like(&self) -> Option<&dyn TableLike> {
        self.as_table()
            .map(|t| t as &dyn TableLike)
            .or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike))
    }

    /// Casts `self` to either a table or an inline table.
    pub fn as_table_like_mut(&mut self) -> Option<&mut dyn TableLike> {
        match self {
            Item::Table(t) => Some(t as &mut dyn TableLike),
            Item::Value(Value::InlineTable(t)) => Some(t as &mut dyn TableLike),
            _ => None,
        }
    }

    /// Returns true iff `self` is either a table, or an inline table.
    pub fn is_table_like(&self) -> bool {
        self.as_table_like().is_some()
    }
}

impl Default for Item {
    fn default() -> Self {
        Item::None
    }
}

impl FromStr for Item {
    type Err = crate::TomlError;

    /// Parses a value from a &str
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let value = s.parse::<Value>()?;
        Ok(Item::Value(value))
    }
}

impl std::fmt::Display for Item {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match &self {
            Item::None => Ok(()),
            Item::Value(v) => v.fmt(f),
            Item::Table(v) => v.fmt(f),
            Item::ArrayOfTables(v) => v.fmt(f),
        }
    }
}

/// Returns a formatted value.
///
/// Since formatting is part of a `Value`, the right hand side of the
/// assignment needs to be decorated with a space before the value.
/// The `value` function does just that.
///
/// # Examples
/// ```rust
/// # use pretty_assertions::assert_eq;
/// # use toml_edit::*;
/// let mut table = Table::default();
/// let mut array = Array::default();
/// array.push("hello");
/// array.push("\\, world"); // \ is only allowed in a literal string
/// table["key1"] = value("value1");
/// table["key2"] = value(42);
/// table["key3"] = value(array);
/// assert_eq!(table.to_string(),
/// r#"key1 = "value1"
/// key2 = 42
/// key3 = ["hello", '\, world']
/// "#);
/// ```
pub fn value<V: Into<Value>>(v: V) -> Item {
    Item::Value(v.into())
}

/// Returns an empty table.
pub fn table() -> Item {
    Item::Table(Table::new())
}

/// Returns an empty array of tables.
pub fn array() -> Item {
    Item::ArrayOfTables(ArrayOfTables::new())
}
<|endoftext|>


<commit_before>use tuple_utils::Split;
use {BitSetAnd, BitSetLike};

/// Join is a helper method to & bitsets togather resulting in a tree
pub trait Join {
    type Value;
    fn join(self) -> Self::Value;
}

impl<A> Join for (A,)
    where A: BitSetLike
{
    type Value = A;
    fn join(self) -> Self::Value {
        self.0
    }
}

impl<A, B> Join for (A, B)
    where A: BitSetLike,
          B: BitSetLike
{
    type Value = BitSetAnd<A,B>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C> Join for (A, B, C)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
{
    type Value = BitSetAnd<A,BitSetAnd<B,C>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D> Join for (A, B, C, D)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<A,B>,BitSetAnd<C,D>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E> Join for (A, B, C, D, E)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<A,B>,BitSetAnd<C,BitSetAnd<D,E>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F> Join for (A, B, C, D, E, F)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<A,BitSetAnd<B,C>>,BitSetAnd<D,BitSetAnd<E,F>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G> Join for (A, B, C, D, E, F, G)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<A,BitSetAnd<B,C>>,BitSetAnd<BitSetAnd<D,E>,BitSetAnd<F,G>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H> Join for (A, B, C, D, E, F, G, H)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,B>,BitSetAnd<C,D>>,BitSetAnd<BitSetAnd<E,F>,BitSetAnd<G,H>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I> Join for (A, B, C, D, E, F, G, H, I)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,B>,BitSetAnd<C,D>>,BitSetAnd<BitSetAnd<E,F>,BitSetAnd<G,BitSetAnd<H,I>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I, J> Join for (A, B, C, D, E, F, G, H, I, J)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
          J: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,B>,BitSetAnd<C,BitSetAnd<D,E>>>,BitSetAnd<BitSetAnd<F,G>,BitSetAnd<H,BitSetAnd<I,J>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I, J, K> Join for (A, B, C, D, E, F, G, H, I, J, K)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
          J: BitSetLike,
          K: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,B>,BitSetAnd<C,BitSetAnd<D,E>>>,BitSetAnd<BitSetAnd<F,BitSetAnd<G,H>>,BitSetAnd<I,BitSetAnd<J,K>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I, J, K, L> Join for (A, B, C, D, E, F, G, H, I, J, K, L)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
          J: BitSetLike,
          K: BitSetLike,
          L: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,BitSetAnd<B,C>>,BitSetAnd<D,BitSetAnd<E,F>>>,BitSetAnd<BitSetAnd<G,BitSetAnd<H,I>>,BitSetAnd<J,BitSetAnd<K,L>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I, J, K, L, M> Join for (A, B, C, D, E, F, G, H, I, J, K, L, M)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
          J: BitSetLike,
          K: BitSetLike,
          L: BitSetLike,
          M: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,BitSetAnd<B,C>>,BitSetAnd<D,BitSetAnd<E,F>>>,BitSetAnd<BitSetAnd<G,BitSetAnd<H,I>>,BitSetAnd<BitSetAnd<J,K>,BitSetAnd<L,M>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I, J, K, L, M, N> Join for (A, B, C, D, E, F, G, H, I, J, K, L, M, N)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
          J: BitSetLike,
          K: BitSetLike,
          L: BitSetLike,
          M: BitSetLike,
          N: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,BitSetAnd<B,C>>,BitSetAnd<BitSetAnd<D,E>,BitSetAnd<F,G>>>,BitSetAnd<BitSetAnd<H,BitSetAnd<I,J>>,BitSetAnd<BitSetAnd<K,L>,BitSetAnd<M,N>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> Join for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
          J: BitSetLike,
          K: BitSetLike,
          L: BitSetLike,
          M: BitSetLike,
          N: BitSetLike,
          O: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<A,BitSetAnd<B,C>>,BitSetAnd<BitSetAnd<D,E>,BitSetAnd<F,G>>>,BitSetAnd<BitSetAnd<BitSetAnd<H,I>,BitSetAnd<J,K>>,BitSetAnd<BitSetAnd<L,M>,BitSetAnd<N,O>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}

impl<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P> Join for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P)
    where A: BitSetLike,
          B: BitSetLike,
          C: BitSetLike,
          D: BitSetLike,
          E: BitSetLike,
          F: BitSetLike,
          G: BitSetLike,
          H: BitSetLike,
          I: BitSetLike,
          J: BitSetLike,
          K: BitSetLike,
          L: BitSetLike,
          M: BitSetLike,
          N: BitSetLike,
          O: BitSetLike,
          P: BitSetLike,
{
    type Value = BitSetAnd<BitSetAnd<BitSetAnd<BitSetAnd<A,B>,BitSetAnd<C,D>>,BitSetAnd<BitSetAnd<E,F>,BitSetAnd<G,H>>>,BitSetAnd<BitSetAnd<BitSetAnd<I,J>,BitSetAnd<K,L>>,BitSetAnd<BitSetAnd<M,N>,BitSetAnd<O,P>>>>;
    fn join(self) -> Self::Value {
        let (l, r) = self.split();
        BitSetAnd(l.join(), r.join())
    }
}
<commit_msg>Use macro to generate Join trait<commit_after>use tuple_utils::Split;
use {BitSetAnd, BitSetLike};

/// Join is a helper method to & bitsets togather resulting in a tree
pub trait Join {
    type Value;
    fn join(self) -> Self::Value;
}

/// This needs to be special cased
impl<A> Join for (A,)
    where A: BitSetLike
{
    type Value = A;
    fn join(self) -> Self::Value {
        self.0
    }
}

macro_rules! merge_impl {
    // use variables to indicate the arity of the tuple
    ($($from:ident),*) => {
      impl<$($from),*> Join for ($($from),*)
          where $($from: BitSetLike),*
      {
          type Value = BitSetAnd<
            <<Self as Split>::Left as Join>::Value,
            <<Self as Split>::Right as Join>::Value
          >;
          fn join(self) -> Self::Value {
              let (l, r) = self.split();
              BitSetAnd(l.join(), r.join())
          }
      }
    }
}

merge_impl!{A, B}
merge_impl!{A, B, C}
merge_impl!{A, B, C, D}
merge_impl!{A, B, C, D, E}
merge_impl!{A, B, C, D, E, F}
merge_impl!{A, B, C, D, E, F, G}
merge_impl!{A, B, C, D, E, F, G, H}
merge_impl!{A, B, C, D, E, F, G, H, I}
merge_impl!{A, B, C, D, E, F, G, H, I, J}
merge_impl!{A, B, C, D, E, F, G, H, I, J, K}
merge_impl!{A, B, C, D, E, F, G, H, I, J, K, L}
merge_impl!{A, B, C, D, E, F, G, H, I, J, K, L, M}
merge_impl!{A, B, C, D, E, F, G, H, I, J, K, L, M, N}
merge_impl!{A, B, C, D, E, F, G, H, I, J, K, L, M, N, O}
merge_impl!{A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P}
<|endoftext|>