<commit_before>// (c) 2016 Productize SPRL <joost@productize.be>

// from parent
use Result;
use str_error;
use footprint;
use Sexp;

/// a Kicad layout
#[derive(Debug)]
pub struct Layout {
    /// version of file
    pub version: i64,
    /// build-host
    pub host: Host,
    /// general information
    pub general: General,
    /// page size
    pub page: String,
    /// setup information
    pub setup: Setup,
    /// layers
    pub layers: Vec<Layer>,
    /// layout elements
    pub elements: Vec<Element>,
}

/// layout elements
#[derive(Clone,Debug)]
pub enum Element {
    /// module
    Module(footprint::Module),
    /// net
    Net(Net),
    /// netclass
    NetClass(NetClass),
    ///  text
    GrText(GrText),
    /// line
    GrLine(GrLine),
    /// arc
    GrArc(GrArc),
    /// dimension
    Dimension(Dimension),
    // Segment,
    // Via,
    // FilledPolygon,
    /// zone
    Zone(Zone),
    /// other (uninterpreted symbolic-expression)
    Other(Sexp),
}

/// a zone region
#[derive(Clone,Debug)]
pub struct Zone {
    /// net number of the zone
    pub net: i64,
    /// net name of the zone
    pub net_name: String,
    /// other (uninterpreted symbolic-expressions)
    pub other: Vec<Sexp>,
}

/// build host info
#[derive(Clone,Debug)]
pub struct Host {
    /// tool name
    pub tool: String,
    /// tool version
    pub build: String,
}

/// general information
#[derive(Clone,Debug)]
pub struct General {
    /// number of links
    pub links: i64,
    /// number of no-connect
    pub no_connects: i64,
    /// area of layout
    pub area: Area,
    /// thickness
    pub thickness: f64,
    /// number of drawings
    pub drawings: i64,
    /// number of tracks
    pub tracks: i64,
    /// number of zones
    pub zones: i64,
    /// number of moduls
    pub modules: i64,
    /// number of nets
    pub nets: i64,
}

/// area
#[derive(Clone,Debug,Default)]
pub struct Area {
    // X1 coordinate
    pub x1: f64,
    // Y1 coordinate
    pub y1: f64,
    // X2 coordinate
    pub x2: f64,
    // Y2 coordinate
    pub y2: f64,
}

/// layer
#[derive(Clone,Debug)]
pub struct Layer {
    /// layer number
    pub num: i64,
    /// layer
    pub layer: footprint::Layer,
    /// layer type
    pub layer_type: LayerType,
    /// if the layer is shown
    pub hide: bool,
}

/// layer type
#[derive(Clone,Debug)]
pub enum LayerType {
    /// signal layer
    Signal,
    /// user layer
    User,
}

#[derive(Clone,Debug,Default)]
pub struct Setup {
    pub elements: Vec<SetupElement>,
    pub pcbplotparams: Vec<SetupElement>,
}

#[derive(Clone,Debug)]
pub struct SetupElement {
    pub name: String,
    pub value1: String,
    pub value2: Option<String>,
}

#[derive(Clone,PartialEq,Debug)]
pub struct Net {
    pub num: i64,
    pub name: String,
}

#[derive(Clone,PartialEq,Debug)]
pub struct NetClass {
    pub name: String,
    pub desc: String,
    pub clearance: f64,
    pub trace_width: f64,
    pub via_dia: f64,
    pub via_drill: f64,
    pub uvia_dia: f64,
    pub uvia_drill: f64,
    pub nets: Vec<String>,
}

#[derive(Clone,Debug)]
pub struct GrText {
    pub value: String,
    pub at: footprint::At,
    pub layer: footprint::Layer,
    pub effects: footprint::Effects,
    pub tstamp: String,
}

// only used internally
pub enum GrElement {
    Start(footprint::Xy),
    End(footprint::Xy),
    Angle(i64),
    Layer(footprint::Layer),
    Width(f64),
    TStamp(String),
    At(footprint::At),
    Effects(footprint::Effects),
}

#[derive(Clone,Debug)]
pub struct GrLine {
    pub start: footprint::Xy,
    pub end: footprint::Xy,
    pub angle: i64,
    pub layer: footprint::Layer,
    pub width: f64,
    pub tstamp: String,
}

#[derive(Clone,Debug)]
pub struct GrArc {
    pub start: footprint::Xy,
    pub end: footprint::Xy,
    pub angle: i64,
    pub layer: footprint::Layer,
    pub width: f64,
    pub tstamp: String,
}

#[derive(Clone,Debug)]
pub struct Dimension {
    pub name: String,
    pub width: f64,
    pub layer: footprint::Layer,
    pub tstamp: Option<String>,
    pub text: GrText,
    pub feature1: footprint::Pts,
    pub feature2: footprint::Pts,
    pub crossbar: footprint::Pts,
    pub arrow1a: footprint::Pts,
    pub arrow1b: footprint::Pts,
    pub arrow2a: footprint::Pts,
    pub arrow2b: footprint::Pts,
}

impl Default for Layout {
    fn default() -> Layout {
        Layout {
            version: 4,
            host: Host::default(),
            elements: vec![],
            setup: Setup::default(),
            general: General::default(),
            page: String::from("A4"),
            layers: vec![],
        }
    }
}

impl Layout {
    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            if let Element::Net(ref net) = *element {
                v.push(net)
            }
        }
        v
    }

    pub fn change_net_name(&mut self, old_name: &str, new_name: &str) {
        // 1. change name in list of nets
        let mut found = false;
        for element in &mut self.elements {
            if let Element::Net(ref mut net) = *element {
                if &net.name == old_name {
                    found = true;
                    net.name.clear();
                    net.name.push_str(new_name);
                }
            }
        }
        if !found {
            return;
        }
        for element in &mut self.elements {
            // 2. change net name in net_class (add_net)
            if let Element::NetClass(ref mut net_class) = *element {
                let mut not_old: Vec<String> =
                    net_class.nets.iter().filter(|&x| &x[..] != old_name).cloned().collect();
                if not_old.len() < net_class.nets.len() {
                    // net was in the net list of the net_class
                    not_old.push(new_name.to_string());
                    net_class.nets = not_old;
                }
            }
            // 3. change net name in pads in modules
            else if let Element::Module(ref mut module) = *element {
                module.rename_net(old_name, new_name)
            }
            // 4. change net name in zones (net_name)
            else if let Element::Zone(ref mut zone) = *element {
                if &zone.net_name == old_name {
                    zone.net_name = new_name.to_string()
                }
            }
        }
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            if let Element::NetClass(ref net_class) = *element {
                v.push(net_class)
            }
        }
        v
    }

    pub fn get_module(&self, reference: &str) -> Option<&footprint::Module> {
        for ref x in &self.elements[..] {
            match **x {
                Element::Module(ref m) => {
                    if m.is_reference_with_name(reference) {
                        return Some(m);
                    }
                }
                Element::Net(_) |
                Element::NetClass(_) |
                Element::GrText(_) |
                Element::GrLine(_) |
                Element::GrArc(_) |
                Element::Dimension(_) |
                Element::Zone(_) |
                Element::Other(_) => (),
            }
        }
        None
    }

    pub fn modify_module<F>(&mut self, reference: &str, fun: F) -> Result<()>
        where F: Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference_with_name(reference) {
                        return Ok(fun(m));
                    }
                }
                Element::Net(_) |
                Element::NetClass(_) |
                Element::GrText(_) |
                Element::GrLine(_) |
                Element::GrArc(_) |
                Element::Dimension(_) |
                Element::Zone(_) |
                Element::Other(_) => (),
            }
        }
        str_error(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num: i64, name: &'static str) {
        self.elements.push(Element::Net(Net {
            num: num,
            name: String::from(name),
        }));
    }
    pub fn add_netclass(&mut self,
                        name: &'static str,
                        desc: &'static str,
                        clearance: f64,
                        trace_width: f64,
                        via_dia: f64,
                        via_drill: f64,
                        uvia_dia: f64,
                        uvia_drill: f64,
                        nets: Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name: String::from(name),
            desc: String::from(desc),
            clearance: clearance,
            trace_width: trace_width,
            via_dia: via_dia,
            via_drill: via_drill,
            uvia_dia: uvia_dia,
            uvia_drill: uvia_drill,
            nets: nets,
        }));
    }
}

impl Default for Host {
    fn default() -> Host {
        Host {
            tool: String::from("pcbnew"),
            build: String::from("custom"),
        }
    }
}

impl Default for General {
    fn default() -> General {
        General {
            links: 0,
            no_connects: 0,
            area: Area::default(),
            thickness: 1.6,
            drawings: 0,
            tracks: 0,
            zones: 0,
            modules: 0,
            nets: 0,
        }
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other: &NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        s1 == s2
    }
    pub fn has_net(&self, name: &'static str) -> bool {
        for net in &self.nets {
            if &net[..] == name {
                return true;
            }
        }
        false
    }
}

impl Setup {
    pub fn get(&self, s: &str) -> Option<&String> {
        for element in &self.elements {
            if &element.name[..] == &s[..] {
                return Some(&element.value1);
            }
        }
        None
    }

    pub fn update_element(&mut self, name: &'static str, value: String) {
        for element in &mut self.elements {
            if &element.name[..] == name {
                element.value1 = value;
                return;

            }
        }
        self.elements.push(SetupElement {
            name: String::from(name),
            value1: value,
            value2: None,
        })
    }
}
<commit_msg>small documentation fix<commit_after>// (c) 2016 Productize SPRL <joost@productize.be>

// from parent
use Result;
use str_error;
use footprint;
use Sexp;

/// a Kicad layout
#[derive(Debug)]
pub struct Layout {
    /// version of file
    pub version: i64,
    /// build-host
    pub host: Host,
    /// general information
    pub general: General,
    /// page size
    pub page: String,
    /// setup information
    pub setup: Setup,
    /// layers
    pub layers: Vec<Layer>,
    /// layout elements
    pub elements: Vec<Element>,
}

/// layout elements
#[derive(Clone,Debug)]
pub enum Element {
    /// module
    Module(footprint::Module),
    /// net
    Net(Net),
    /// netclass
    NetClass(NetClass),
    ///  text
    GrText(GrText),
    /// line
    GrLine(GrLine),
    /// arc
    GrArc(GrArc),
    /// dimension
    Dimension(Dimension),
    // Segment,
    // Via,
    // FilledPolygon,
    /// zone
    Zone(Zone),
    /// other (uninterpreted symbolic-expression)
    Other(Sexp),
}

/// a zone region
#[derive(Clone,Debug)]
pub struct Zone {
    /// net number of the zone
    pub net: i64,
    /// net name of the zone
    pub net_name: String,
    /// other (uninterpreted symbolic-expressions)
    pub other: Vec<Sexp>,
}

/// build host info
#[derive(Clone,Debug)]
pub struct Host {
    /// tool name
    pub tool: String,
    /// tool version
    pub build: String,
}

/// general information
#[derive(Clone,Debug)]
pub struct General {
    /// number of links
    pub links: i64,
    /// number of no-connect
    pub no_connects: i64,
    /// area of layout
    pub area: Area,
    /// thickness
    pub thickness: f64,
    /// number of drawings
    pub drawings: i64,
    /// number of tracks
    pub tracks: i64,
    /// number of zones
    pub zones: i64,
    /// number of moduls
    pub modules: i64,
    /// number of nets
    pub nets: i64,
}

/// area
#[derive(Clone,Debug,Default)]
pub struct Area {
    // X1 coordinate
    pub x1: f64,
    // Y1 coordinate
    pub y1: f64,
    // X2 coordinate
    pub x2: f64,
    // Y2 coordinate
    pub y2: f64,
}

/// layer
#[derive(Clone,Debug)]
pub struct Layer {
    /// layer number
    pub num: i64,
    /// layer
    pub layer: footprint::Layer,
    /// layer type
    pub layer_type: LayerType,
    /// if the layer is shown
    pub hide: bool,
}

/// layer type
#[derive(Clone,Debug)]
pub enum LayerType {
    /// signal layer
    Signal,
    /// user layer
    User,
}

/// setup elements of the layout
#[derive(Clone,Debug,Default)]
pub struct Setup {
    /// the setup elements
    pub elements: Vec<SetupElement>,
    /// the pcb plot elements
    pub pcbplotparams: Vec<SetupElement>,
}

/// a generic setup element
#[derive(Clone,Debug)]
pub struct SetupElement {
    /// a name
    pub name: String,
    /// a first value
    pub value1: String,
    /// an optional second value
    pub value2: Option<String>,
}

#[derive(Clone,PartialEq,Debug)]
pub struct Net {
    pub num: i64,
    pub name: String,
}

#[derive(Clone,PartialEq,Debug)]
pub struct NetClass {
    pub name: String,
    pub desc: String,
    pub clearance: f64,
    pub trace_width: f64,
    pub via_dia: f64,
    pub via_drill: f64,
    pub uvia_dia: f64,
    pub uvia_drill: f64,
    pub nets: Vec<String>,
}

#[derive(Clone,Debug)]
pub struct GrText {
    pub value: String,
    pub at: footprint::At,
    pub layer: footprint::Layer,
    pub effects: footprint::Effects,
    pub tstamp: String,
}

// only used internally
pub enum GrElement {
    Start(footprint::Xy),
    End(footprint::Xy),
    Angle(i64),
    Layer(footprint::Layer),
    Width(f64),
    TStamp(String),
    At(footprint::At),
    Effects(footprint::Effects),
}

#[derive(Clone,Debug)]
pub struct GrLine {
    pub start: footprint::Xy,
    pub end: footprint::Xy,
    pub angle: i64,
    pub layer: footprint::Layer,
    pub width: f64,
    pub tstamp: String,
}

#[derive(Clone,Debug)]
pub struct GrArc {
    pub start: footprint::Xy,
    pub end: footprint::Xy,
    pub angle: i64,
    pub layer: footprint::Layer,
    pub width: f64,
    pub tstamp: String,
}

#[derive(Clone,Debug)]
pub struct Dimension {
    pub name: String,
    pub width: f64,
    pub layer: footprint::Layer,
    pub tstamp: Option<String>,
    pub text: GrText,
    pub feature1: footprint::Pts,
    pub feature2: footprint::Pts,
    pub crossbar: footprint::Pts,
    pub arrow1a: footprint::Pts,
    pub arrow1b: footprint::Pts,
    pub arrow2a: footprint::Pts,
    pub arrow2b: footprint::Pts,
}

impl Default for Layout {
    fn default() -> Layout {
        Layout {
            version: 4,
            host: Host::default(),
            elements: vec![],
            setup: Setup::default(),
            general: General::default(),
            page: String::from("A4"),
            layers: vec![],
        }
    }
}

impl Layout {
    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            if let Element::Net(ref net) = *element {
                v.push(net)
            }
        }
        v
    }

    pub fn change_net_name(&mut self, old_name: &str, new_name: &str) {
        // 1. change name in list of nets
        let mut found = false;
        for element in &mut self.elements {
            if let Element::Net(ref mut net) = *element {
                if &net.name == old_name {
                    found = true;
                    net.name.clear();
                    net.name.push_str(new_name);
                }
            }
        }
        if !found {
            return;
        }
        for element in &mut self.elements {
            // 2. change net name in net_class (add_net)
            if let Element::NetClass(ref mut net_class) = *element {
                let mut not_old: Vec<String> =
                    net_class.nets.iter().filter(|&x| &x[..] != old_name).cloned().collect();
                if not_old.len() < net_class.nets.len() {
                    // net was in the net list of the net_class
                    not_old.push(new_name.to_string());
                    net_class.nets = not_old;
                }
            }
            // 3. change net name in pads in modules
            else if let Element::Module(ref mut module) = *element {
                module.rename_net(old_name, new_name)
            }
            // 4. change net name in zones (net_name)
            else if let Element::Zone(ref mut zone) = *element {
                if &zone.net_name == old_name {
                    zone.net_name = new_name.to_string()
                }
            }
        }
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            if let Element::NetClass(ref net_class) = *element {
                v.push(net_class)
            }
        }
        v
    }

    pub fn get_module(&self, reference: &str) -> Option<&footprint::Module> {
        for ref x in &self.elements[..] {
            match **x {
                Element::Module(ref m) => {
                    if m.is_reference_with_name(reference) {
                        return Some(m);
                    }
                }
                Element::Net(_) |
                Element::NetClass(_) |
                Element::GrText(_) |
                Element::GrLine(_) |
                Element::GrArc(_) |
                Element::Dimension(_) |
                Element::Zone(_) |
                Element::Other(_) => (),
            }
        }
        None
    }

    pub fn modify_module<F>(&mut self, reference: &str, fun: F) -> Result<()>
        where F: Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference_with_name(reference) {
                        return Ok(fun(m));
                    }
                }
                Element::Net(_) |
                Element::NetClass(_) |
                Element::GrText(_) |
                Element::GrLine(_) |
                Element::GrArc(_) |
                Element::Dimension(_) |
                Element::Zone(_) |
                Element::Other(_) => (),
            }
        }
        str_error(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num: i64, name: &'static str) {
        self.elements.push(Element::Net(Net {
            num: num,
            name: String::from(name),
        }));
    }
    pub fn add_netclass(&mut self,
                        name: &'static str,
                        desc: &'static str,
                        clearance: f64,
                        trace_width: f64,
                        via_dia: f64,
                        via_drill: f64,
                        uvia_dia: f64,
                        uvia_drill: f64,
                        nets: Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name: String::from(name),
            desc: String::from(desc),
            clearance: clearance,
            trace_width: trace_width,
            via_dia: via_dia,
            via_drill: via_drill,
            uvia_dia: uvia_dia,
            uvia_drill: uvia_drill,
            nets: nets,
        }));
    }
}

impl Default for Host {
    fn default() -> Host {
        Host {
            tool: String::from("pcbnew"),
            build: String::from("custom"),
        }
    }
}

impl Default for General {
    fn default() -> General {
        General {
            links: 0,
            no_connects: 0,
            area: Area::default(),
            thickness: 1.6,
            drawings: 0,
            tracks: 0,
            zones: 0,
            modules: 0,
            nets: 0,
        }
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other: &NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        s1 == s2
    }
    pub fn has_net(&self, name: &'static str) -> bool {
        for net in &self.nets {
            if &net[..] == name {
                return true;
            }
        }
        false
    }
}

impl Setup {
    pub fn get(&self, s: &str) -> Option<&String> {
        for element in &self.elements {
            if &element.name[..] == &s[..] {
                return Some(&element.value1);
            }
        }
        None
    }

    pub fn update_element(&mut self, name: &'static str, value: String) {
        for element in &mut self.elements {
            if &element.name[..] == name {
                element.value1 = value;
                return;

            }
        }
        self.elements.push(SetupElement {
            name: String::from(name),
            value1: value,
            value2: None,
        })
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "", since = "1.30.0")]

#![allow(non_camel_case_types)]

//! Utilities related to FFI bindings.

use ::fmt;

/// Equivalent to C's `void` type when used as a [pointer].
///
/// In essence, `*const c_void` is equivalent to C's `const void*`
/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
/// *not* the same as C's `void` return type, which is Rust's `()` type.
///
/// Ideally, this type would be equivalent to [`!`], but currently it may
/// be more ideal to use `c_void` for FFI purposes.
///
/// [`!`]: ../../std/primitive.never.html
/// [pointer]: ../../std/primitive.pointer.html
// N.B., for LLVM to recognize the void pointer type and by extension
//     functions like malloc(), we need to have it represented as i8* in
//     LLVM bitcode. The enum used here ensures this and prevents misuse
//     of the "raw" type by only having private variants.. We need two
//     variants, because the compiler complains about the repr attribute
//     otherwise.
#[repr(u8)]
#[stable(feature = "raw_os", since = "1.1.0")]
pub enum c_void {
    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
               issue = "0")]
    #[doc(hidden)] __variant1,
    #[unstable(feature = "c_void_variant", reason = "should not have to exist",
               issue = "0")]
    #[doc(hidden)] __variant2,
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for c_void {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("c_void")
    }
}

/// Basic implementation of a `va_list`.
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          all(target_arch = "aarch4", target_os = "ios"),
          windows))]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
extern {
    type VaListImpl;
}

#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          windows))]
impl fmt::Debug for VaListImpl {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "va_list* {:p}", self)
    }
}

/// AArch64 ABI implementation of a `va_list`. See the
/// [Aarch64 Procedure Call Standard] for more details.
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg(all(target_arch = "aarch64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
struct VaListImpl {
    stack: *mut (),
    gr_top: *mut (),
    vr_top: *mut (),
    gr_offs: i32,
    vr_offs: i32,
}

/// PowerPC ABI implementation of a `va_list`.
#[cfg(all(target_arch = "powerpc", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
struct VaListImpl {
    gpr: u8,
    fpr: u8,
    reserved: u16,
    overflow_arg_area: *mut (),
    reg_save_area: *mut (),
}

/// x86_64 ABI implementation of a `va_list`.
#[cfg(all(target_arch = "x86_64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
struct VaListImpl {
    gp_offset: i32,
    fp_offset: i32,
    overflow_arg_area: *mut (),
    reg_save_area: *mut (),
}

/// A wrapper for a `va_list`
#[lang = "va_list"]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
#[repr(transparent)]
pub struct VaList<'a>(&'a mut VaListImpl);

// The VaArgSafe trait needs to be used in public interfaces, however, the trait
// itself must not be allowed to be used outside this module. Allowing users to
// implement the trait for a new type (thereby allowing the va_arg intrinsic to
// be used on a new type) is likely to cause undefined behavior.
//
// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
// but also ensure it cannot be used elsewhere, the trait needs to be public
// within a private module. Once RFC 2145 has been implemented look into
// improving this.
mod sealed_trait {
    /// Trait which whitelists the allowed types to be used with [VaList::arg]
    ///
    /// [VaList::va_arg]: struct.VaList.html#method.arg
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "27745")]
    pub trait VaArgSafe {}
}

macro_rules! impl_va_arg_safe {
    ($($t:ty),+) => {
        $(
            #[unstable(feature = "c_variadic",
                       reason = "the `c_variadic` feature has not been properly tested on \
                                 all supported platforms",
                       issue = "27745")]
            impl sealed_trait::VaArgSafe for $t {}
        )+
    }
}

impl_va_arg_safe!{i8, i16, i32, i64, usize}
impl_va_arg_safe!{u8, u16, u32, u64, isize}
impl_va_arg_safe!{f64}

#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
impl<T> sealed_trait::VaArgSafe for *mut T {}
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
impl<T> sealed_trait::VaArgSafe for *const T {}

impl<'a> VaList<'a> {
    /// Advance to the next arg.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "27745")]
    pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
        va_arg(self)
    }

    /// Copy the `va_list` at the current location.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "27745")]
    pub unsafe fn copy<F, R>(&self, f: F) -> R
            where F: for<'copy> FnOnce(VaList<'copy>) -> R {
        #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                      not(target_arch = "x86_64")),
                  all(target_arch = "aarch4", target_os = "ios"),
                  windows))]
        let mut ap = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows)))]
        let mut ap_inner = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows)))]
        let mut ap = VaList(&mut ap_inner);
        let ret = f(VaList(ap.0));
        va_end(&mut ap);
        ret
    }
}

extern "rust-intrinsic" {
    /// Destroy the arglist `ap` after initialization with `va_start` or
    /// `va_copy`.
    fn va_end(ap: &mut VaList);

    /// Copy the current location of arglist `src` to the arglist `dst`.
    #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                  not(target_arch = "x86_64")),
              windows))]
    fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>;
    #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
              not(windows)))]
    fn va_copy(src: &VaList) -> VaListImpl;

    /// Loads an argument of type `T` from the `va_list` `ap` and increment the
    /// argument `ap` points to.
    fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaList) -> T;
}
<commit_msg>Rollup merge of #56594 - sdroege:c_void-is-not-never, r=TimNN<commit_after>#![stable(feature = "", since = "1.30.0")]

#![allow(non_camel_case_types)]

//! Utilities related to FFI bindings.

use ::fmt;

/// Equivalent to C's `void` type when used as a [pointer].
///
/// In essence, `*const c_void` is equivalent to C's `const void*`
/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
/// *not* the same as C's `void` return type, which is Rust's `()` type.
///
/// To model pointers to opaque types in FFI, until `extern type` is
/// stabilized, it is recommended to use a newtype wrapper around an empty
/// byte array. See the [Nomicon] for details.
///
/// [pointer]: ../../std/primitive.pointer.html
/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
// N.B., for LLVM to recognize the void pointer type and by extension
//     functions like malloc(), we need to have it represented as i8* in
//     LLVM bitcode. The enum used here ensures this and prevents misuse
//     of the "raw" type by only having private variants. We need two
//     variants, because the compiler complains about the repr attribute
//     otherwise and we need at least one variant as otherwise the enum
//     would be uninhabited and at least dereferencing such pointers would
//     be UB.
#[repr(u8)]
#[stable(feature = "raw_os", since = "1.1.0")]
pub enum c_void {
    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
               issue = "0")]
    #[doc(hidden)] __variant1,
    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
               issue = "0")]
    #[doc(hidden)] __variant2,
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for c_void {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("c_void")
    }
}

/// Basic implementation of a `va_list`.
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          all(target_arch = "aarch4", target_os = "ios"),
          windows))]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
extern {
    type VaListImpl;
}

#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          windows))]
impl fmt::Debug for VaListImpl {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "va_list* {:p}", self)
    }
}

/// AArch64 ABI implementation of a `va_list`. See the
/// [Aarch64 Procedure Call Standard] for more details.
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg(all(target_arch = "aarch64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
struct VaListImpl {
    stack: *mut (),
    gr_top: *mut (),
    vr_top: *mut (),
    gr_offs: i32,
    vr_offs: i32,
}

/// PowerPC ABI implementation of a `va_list`.
#[cfg(all(target_arch = "powerpc", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
struct VaListImpl {
    gpr: u8,
    fpr: u8,
    reserved: u16,
    overflow_arg_area: *mut (),
    reg_save_area: *mut (),
}

/// x86_64 ABI implementation of a `va_list`.
#[cfg(all(target_arch = "x86_64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
struct VaListImpl {
    gp_offset: i32,
    fp_offset: i32,
    overflow_arg_area: *mut (),
    reg_save_area: *mut (),
}

/// A wrapper for a `va_list`
#[lang = "va_list"]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
#[repr(transparent)]
pub struct VaList<'a>(&'a mut VaListImpl);

// The VaArgSafe trait needs to be used in public interfaces, however, the trait
// itself must not be allowed to be used outside this module. Allowing users to
// implement the trait for a new type (thereby allowing the va_arg intrinsic to
// be used on a new type) is likely to cause undefined behavior.
//
// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
// but also ensure it cannot be used elsewhere, the trait needs to be public
// within a private module. Once RFC 2145 has been implemented look into
// improving this.
mod sealed_trait {
    /// Trait which whitelists the allowed types to be used with [VaList::arg]
    ///
    /// [VaList::va_arg]: struct.VaList.html#method.arg
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "27745")]
    pub trait VaArgSafe {}
}

macro_rules! impl_va_arg_safe {
    ($($t:ty),+) => {
        $(
            #[unstable(feature = "c_variadic",
                       reason = "the `c_variadic` feature has not been properly tested on \
                                 all supported platforms",
                       issue = "27745")]
            impl sealed_trait::VaArgSafe for $t {}
        )+
    }
}

impl_va_arg_safe!{i8, i16, i32, i64, usize}
impl_va_arg_safe!{u8, u16, u32, u64, isize}
impl_va_arg_safe!{f64}

#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
impl<T> sealed_trait::VaArgSafe for *mut T {}
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
impl<T> sealed_trait::VaArgSafe for *const T {}

impl<'a> VaList<'a> {
    /// Advance to the next arg.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "27745")]
    pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
        va_arg(self)
    }

    /// Copy the `va_list` at the current location.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "27745")]
    pub unsafe fn copy<F, R>(&self, f: F) -> R
            where F: for<'copy> FnOnce(VaList<'copy>) -> R {
        #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                      not(target_arch = "x86_64")),
                  all(target_arch = "aarch4", target_os = "ios"),
                  windows))]
        let mut ap = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows)))]
        let mut ap_inner = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows)))]
        let mut ap = VaList(&mut ap_inner);
        let ret = f(VaList(ap.0));
        va_end(&mut ap);
        ret
    }
}

extern "rust-intrinsic" {
    /// Destroy the arglist `ap` after initialization with `va_start` or
    /// `va_copy`.
    fn va_end(ap: &mut VaList);

    /// Copy the current location of arglist `src` to the arglist `dst`.
    #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                  not(target_arch = "x86_64")),
              windows))]
    fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>;
    #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
              not(windows)))]
    fn va_copy(src: &VaList) -> VaListImpl;

    /// Loads an argument of type `T` from the `va_list` `ap` and increment the
    /// argument `ap` points to.
    fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaList) -> T;
}
<|endoftext|>


<commit_before>use libc::c_void;
use std::c_str::ToCStr;
use std::mem::transmute;
use std::ptr::RawPtr;
use std::str::raw::from_c_str;
/// A structure that wraps a native object
pub trait NativeRef {
    /// Returns the native reference encapsulated by this object
    unsafe fn as_ptr(&self) -> *mut c_void;
    /// Returns a wrapped version of the native reference given, even if the reference is null
    unsafe fn from_ptr(ptr:*mut c_void) -> Self;
    #[inline(always)]
    /// Works with the internal pointer in a closure
    unsafe fn with_ptr<R>(&self, cb:|*mut c_void| -> R) -> R {
        cb(self.as_ptr())
    }
}
impl<T:NativeRef> NativeRef for Option<T> {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> *mut c_void {
        match *self {
            Some(ref v) => v.as_ptr(),
            None => RawPtr::null()
        }
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:*mut c_void) -> Option<T> {
        if ptr.is_null() {
            None
        } else {
            Some(NativeRef::from_ptr(ptr))
        }
    }
}
impl NativeRef for String {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> *mut c_void {
        transmute(self.to_c_str().unwrap())
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:*mut c_void) -> String {
        from_c_str(transmute(ptr))
    }
    #[inline(always)]
    unsafe fn with_ptr<R>(&self, cb:|*mut c_void| -> R) -> R {
        self.with_c_str(transmute(cb))
    }
}<commit_msg>Implement `NativeRef` for `CString`<commit_after>use libc::c_void;
use std::c_str::{CString, ToCStr};
use std::mem::transmute;
use std::ptr::RawPtr;
use std::str::raw::from_c_str;
/// A structure that wraps a native object
pub trait NativeRef {
    /// Returns the native reference encapsulated by this object
    unsafe fn as_ptr(&self) -> *mut c_void;
    /// Returns a wrapped version of the native reference given, even if the reference is null
    unsafe fn from_ptr(ptr:*mut c_void) -> Self;
    #[inline(always)]
    /// Works with the internal pointer in a closure
    unsafe fn with_ptr<R>(&self, cb:|*mut c_void| -> R) -> R {
        cb(self.as_ptr())
    }
}
impl<T:NativeRef> NativeRef for Option<T> {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> *mut c_void {
        match *self {
            Some(ref v) => v.as_ptr(),
            None => RawPtr::null()
        }
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:*mut c_void) -> Option<T> {
        if ptr.is_null() {
            None
        } else {
            Some(NativeRef::from_ptr(ptr))
        }
    }
}
impl NativeRef for String {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> *mut c_void {
        transmute(self.to_c_str().unwrap())
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:*mut c_void) -> String {
        from_c_str(transmute(ptr))
    }
    #[inline(always)]
    unsafe fn with_ptr<R>(&self, cb:|*mut c_void| -> R) -> R {
        self.with_c_str(transmute(cb))
    }
}
impl NativeRef for CString {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> *mut c_void {
        transmute(self.with_ref(|ptr| ptr))
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:*mut c_void) -> CString {
        CString::new(transmute(ptr), true)
    }
    #[inline(always)]
    unsafe fn with_ptr<R>(&self, cb:|*mut c_void| -> R) -> R {
        self.with_ref(transmute(cb))
    }
}<|endoftext|>


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

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it. This
 * can be used for various acts of magick.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/**
 * Force-increment the reference count on a shared box. If used
 * carelessly, this can leak the box.
 */
#[inline]
pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::{bump_box_refcount, transmute};
    use raw;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_bump_managed_refcount() {
        unsafe {
            let managed = @~"box box box";      // refcount 1
            bump_box_refcount(managed);     // refcount 2
            let ptr: *int = transmute(managed); // refcount 2
            let _box1: @~str = ::cast::transmute_copy(&ptr);
            let _box2: @~str = ::cast::transmute_copy(&ptr);
            assert!(*_box1 == ~"box box box");
            assert!(*_box2 == ~"box box box");
            // Will destroy _box1 and _box2. Without the bump, this would
            // use-after-free. With too many bumps, it would leak.
        }
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(~[76u8], transmute(~"L"));
        }
    }
}
<commit_msg>remove meaningless sentence and update copyright.<commit_after>// Copyright 2012-2013 The Rust Project Developers.
// See the COPYRIGHT file at the top-level directory of this
// distribution and at // http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/**
 * Force-increment the reference count on a shared box. If used
 * carelessly, this can leak the box.
 */
#[inline]
pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::{bump_box_refcount, transmute};
    use raw;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_bump_managed_refcount() {
        unsafe {
            let managed = @~"box box box";      // refcount 1
            bump_box_refcount(managed);     // refcount 2
            let ptr: *int = transmute(managed); // refcount 2
            let _box1: @~str = ::cast::transmute_copy(&ptr);
            let _box2: @~str = ::cast::transmute_copy(&ptr);
            assert!(*_box1 == ~"box box box");
            assert!(*_box2 == ~"box box box");
            // Will destroy _box1 and _box2. Without the bump, this would
            // use-after-free. With too many bumps, it would leak.
        }
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(~[76u8], transmute(~"L"));
        }
    }
}
<|endoftext|>


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

//! Miscellaneous helpers for common patterns

use cast;
use ptr;
use prelude::*;
use unstable::intrinsics;

/// The identity function.
#[inline]
pub fn id<T>(x: T) -> T { x }

/**
 * Swap the values at two mutable locations of the same type, without
 * deinitialising or copying either one.
 */
#[inline]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut tmp: T = intrinsics::uninit();
        let t: *mut T = &mut tmp;

        // Perform the swap, `&mut` pointers never alias
        let x_raw: *mut T = x;
        let y_raw: *mut T = y;
        ptr::copy_nonoverlapping_memory(t, x_raw, 1);
        ptr::copy_nonoverlapping_memory(x, y_raw, 1);
        ptr::copy_nonoverlapping_memory(y, t, 1);

        // y and t now point to the same thing, but we need to completely forget `tmp`
        // because it's no longer relevant.
        cast::forget(tmp);
    }
}

/**
 * Replace the value at a mutable location with a new one, returning the old
 * value, without deinitialising or copying either one.
 */
#[inline]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// A non-copyable dummy type.
#[deriving(Eq, TotalEq, Ord, TotalOrd)]
#[unsafe_no_drop_flag]
pub struct NonCopyable;

impl Drop for NonCopyable {
    fn drop(&mut self) { }
}

/// A type with no inhabitants
pub enum Void { }

impl Void {
    /// A utility function for ignoring this uninhabited type
    pub fn uninhabited(self) -> ! {
        match self {
            // Nothing to match on
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use prelude::*;
    use mem::size_of;

    #[test]
    fn identity_crisis() {
        // Writing a test for the identity function. How did it come to this?
        let x = ~[(5, false)];
        //FIXME #3387 assert!(x.eq(id(x.clone())));
        let y = x.clone();
        assert!(x.eq(&id(y)));
    }

    #[test]
    fn test_swap() {
        let mut x = 31337;
        let mut y = 42;
        swap(&mut x, &mut y);
        assert_eq!(x, 42);
        assert_eq!(y, 31337);
    }

    #[test]
    fn test_replace() {
        let mut x = Some(NonCopyable);
        let y = replace(&mut x, None);
        assert!(x.is_none());
        assert!(y.is_some());
    }

    #[test]
    fn test_noncopyable() {
        assert_eq!(size_of::<NonCopyable>(), 0);

        // verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct

        static mut did_run: bool = false;

        struct Foo { five: int }

        impl Drop for Foo {
            fn drop(&mut self) {
                assert_eq!(self.five, 5);
                unsafe {
                    did_run = true;
                }
            }
        }

        {
            let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
        }

        unsafe { assert_eq!(did_run, true); }
    }
}

/// Completely miscellaneous language-constracuct benchmarks.
#[cfg(test)]
mod bench {

    use extra::test::BenchHarness;
    use option::{Some,None};

    // Static/dynamic method dispatch

    struct Struct {
        field: int
    }

    trait Trait {
        fn method(&self) -> int;
    }

    impl Trait for Struct {
        fn method(&self) -> int {
            self.field
        }
    }

    #[bench]
    fn trait_vtable_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        let t = &s as &Trait;
        bh.iter(|| {
            t.method();
        });
    }

    #[bench]
    fn trait_static_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        bh.iter(|| {
            s.method();
        });
    }

    // Overhead of various match forms

    #[bench]
    fn match_option_some(bh: &mut BenchHarness) {
        let x = Some(10);
        bh.iter(|| {
            let _q = match x {
                Some(y) => y,
                None => 11
            };
        });
    }

    #[bench]
    fn match_vec_pattern(bh: &mut BenchHarness) {
        let x = [1,2,3,4,5,6];
        bh.iter(|| {
            let _q = match x {
                [1,2,3,..] => 10,
                _ => 11
            };
        });
    }
}
<commit_msg>Remove typo<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Miscellaneous helpers for common patterns

use cast;
use ptr;
use prelude::*;
use unstable::intrinsics;

/// The identity function.
#[inline]
pub fn id<T>(x: T) -> T { x }

/**
 * Swap the values at two mutable locations of the same type, without
 * deinitialising or copying either one.
 */
#[inline]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut tmp: T = intrinsics::uninit();
        let t: *mut T = &mut tmp;

        // Perform the swap, `&mut` pointers never alias
        let x_raw: *mut T = x;
        let y_raw: *mut T = y;
        ptr::copy_nonoverlapping_memory(t, x_raw, 1);
        ptr::copy_nonoverlapping_memory(x, y_raw, 1);
        ptr::copy_nonoverlapping_memory(y, t, 1);

        // y and t now point to the same thing, but we need to completely forget `tmp`
        // because it's no longer relevant.
        cast::forget(tmp);
    }
}

/**
 * Replace the value at a mutable location with a new one, returning the old
 * value, without deinitialising or copying either one.
 */
#[inline]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// A non-copyable dummy type.
#[deriving(Eq, TotalEq, Ord, TotalOrd)]
#[unsafe_no_drop_flag]
pub struct NonCopyable;

impl Drop for NonCopyable {
    fn drop(&mut self) { }
}

/// A type with no inhabitants
pub enum Void { }

impl Void {
    /// A utility function for ignoring this uninhabited type
    pub fn uninhabited(self) -> ! {
        match self {
            // Nothing to match on
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use prelude::*;
    use mem::size_of;

    #[test]
    fn identity_crisis() {
        // Writing a test for the identity function. How did it come to this?
        let x = ~[(5, false)];
        //FIXME #3387 assert!(x.eq(id(x.clone())));
        let y = x.clone();
        assert!(x.eq(&id(y)));
    }

    #[test]
    fn test_swap() {
        let mut x = 31337;
        let mut y = 42;
        swap(&mut x, &mut y);
        assert_eq!(x, 42);
        assert_eq!(y, 31337);
    }

    #[test]
    fn test_replace() {
        let mut x = Some(NonCopyable);
        let y = replace(&mut x, None);
        assert!(x.is_none());
        assert!(y.is_some());
    }

    #[test]
    fn test_noncopyable() {
        assert_eq!(size_of::<NonCopyable>(), 0);

        // verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct

        static mut did_run: bool = false;

        struct Foo { five: int }

        impl Drop for Foo {
            fn drop(&mut self) {
                assert_eq!(self.five, 5);
                unsafe {
                    did_run = true;
                }
            }
        }

        {
            let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
        }

        unsafe { assert_eq!(did_run, true); }
    }
}

/// Completely miscellaneous language-construct benchmarks.
#[cfg(test)]
mod bench {

    use extra::test::BenchHarness;
    use option::{Some,None};

    // Static/dynamic method dispatch

    struct Struct {
        field: int
    }

    trait Trait {
        fn method(&self) -> int;
    }

    impl Trait for Struct {
        fn method(&self) -> int {
            self.field
        }
    }

    #[bench]
    fn trait_vtable_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        let t = &s as &Trait;
        bh.iter(|| {
            t.method();
        });
    }

    #[bench]
    fn trait_static_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        bh.iter(|| {
            s.method();
        });
    }

    // Overhead of various match forms

    #[bench]
    fn match_option_some(bh: &mut BenchHarness) {
        let x = Some(10);
        bh.iter(|| {
            let _q = match x {
                Some(y) => y,
                None => 11
            };
        });
    }

    #[bench]
    fn match_vec_pattern(bh: &mut BenchHarness) {
        let x = [1,2,3,4,5,6];
        bh.iter(|| {
            let _q = match x {
                [1,2,3,..] => 10,
                _ => 11
            };
        });
    }
}
<|endoftext|>


<commit_before>use address::{LENGTH, Address, Addressable};
use node::Node;
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

#[derive(Debug)]
pub struct NodeBucket {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, Box<Node>>
}

impl NodeBucket {
    pub fn new(k: usize) -> NodeBucket {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn get_nodes(&self) -> Vec<&Box<Node>> {
        self.nodes.iter().map(|(_, node)| node).collect()
    }

    pub fn insert(&mut self, node: Box<Node>) {
        let address = node.get_address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let difference = self.max.clone() - self.min.clone();
        let partition = difference / 2.to_biguint().unwrap() + self.min.clone();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use node::{Node, Serialize};
    use messages;
    use super::NodeBucket;

    #[derive(Debug)]
    struct TestNode {
        pub address: Address
    }

    impl TestNode {
        fn new(address: Address) -> TestNode {
            TestNode { address: address }
        }
    }

    impl Addressable for TestNode {
        fn get_address(&self) -> Address {
            self.address
        }
    }

    impl Node for TestNode {
        fn update(&mut self) { }
        fn send(&self, _: Vec<u8>) { }
    }

    impl Serialize for TestNode {
        fn serialize(&self) -> messages::protobufs::Node {
            messages::protobufs::Node::new()
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node = Box::new(TestNode::new(Address::for_content("some string")));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let addr_1 = Address::for_content("node 1");
        let addr_2 = Address::for_content("node 2");
        let addr_3 = Address::for_content("node 1");
        let a = Box::new(TestNode::new(addr_1));
        let b = Box::new(TestNode::new(addr_2));
        let c = Box::new(TestNode::new(addr_3));

        bucket.insert(a);
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")].get_address(), addr_1);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 3"))));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket = NodeBucket::new(4);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000000");
        let addr_2 = Address::from_str("7fffffffffffffffffffffffffffffffffffffff");
        let addr_3 = Address::from_str("8000000000000000000000000000000000000000");
        let addr_4 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        let node_4 = Box::new(TestNode::new(addr_4));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")].get_address(), addr_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")].get_address(), addr_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")].get_address(), addr_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<commit_msg>Add simplified Debug trait for NodeBucket<commit_after>use address::{LENGTH, Address, Addressable};
use node::Node;
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use std::fmt;
use num;

pub struct NodeBucket {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, Box<Node>>
}

impl fmt::Debug for NodeBucket {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "NodeBucket {{ {:040x} - {:040x}, {} }}", self.min, self.max, self.addresses.len())
    }
}

impl NodeBucket {
    pub fn new(k: usize) -> NodeBucket {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn get_nodes(&self) -> Vec<&Box<Node>> {
        self.nodes.iter().map(|(_, node)| node).collect()
    }

    pub fn insert(&mut self, node: Box<Node>) {
        let address = node.get_address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let difference = self.max.clone() - self.min.clone();
        let partition = difference / 2.to_biguint().unwrap() + self.min.clone();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use node::{Node, Serialize};
    use messages;
    use super::NodeBucket;

    #[derive(Debug)]
    struct TestNode {
        pub address: Address
    }

    impl TestNode {
        fn new(address: Address) -> TestNode {
            TestNode { address: address }
        }
    }

    impl Addressable for TestNode {
        fn get_address(&self) -> Address {
            self.address
        }
    }

    impl Node for TestNode {
        fn update(&mut self) { }
        fn send(&self, _: Vec<u8>) { }
    }

    impl Serialize for TestNode {
        fn serialize(&self) -> messages::protobufs::Node {
            messages::protobufs::Node::new()
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node = Box::new(TestNode::new(Address::for_content("some string")));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let addr_1 = Address::for_content("node 1");
        let addr_2 = Address::for_content("node 2");
        let addr_3 = Address::for_content("node 1");
        let a = Box::new(TestNode::new(addr_1));
        let b = Box::new(TestNode::new(addr_2));
        let c = Box::new(TestNode::new(addr_3));

        bucket.insert(a);
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")].get_address(), addr_1);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 3"))));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2"))));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1"))));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket = NodeBucket::new(4);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000000");
        let addr_2 = Address::from_str("7fffffffffffffffffffffffffffffffffffffff");
        let addr_3 = Address::from_str("8000000000000000000000000000000000000000");
        let addr_4 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        let node_4 = Box::new(TestNode::new(addr_4));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")].get_address(), addr_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")].get_address(), addr_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")].get_address(), addr_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<|endoftext|>


<commit_before>/// The definitions for every function used in prelude
/// "The built in functions"
/// These special functions allow for things like defining operators,
/// performing basic operations and special math functions

mod numeric;

use std::io::prelude::*;

use api::parse;

use eval::context_item::ContextItem;
use eval::eval_context::EvalContext;
use eval::built_in_function::BuiltInFunction;

use prelude::numeric::define_math;

pub fn setup_prelude(context: &mut EvalContext) {
    define_math(context);
}

pub fn define_built_in(
    context: &mut EvalContext,
    name: &str,
    params: usize,
    function: BuiltInFunction,
) {
    let item = ContextItem::built_in_defaults(function, params);
    context.set(name, item);
}

pub fn apply_program(context: &mut EvalContext, string: &str) {
    let prog = parse(string).expect("Parse error");

    for statement in prog {
        context.apply(statement);
    }
}

<commit_msg>Fixing warnings in prelude that were allowing errors to go undetected<commit_after>/// The definitions for every function used in prelude
/// "The built in functions"
/// These special functions allow for things like defining operators,
/// performing basic operations and special math functions

mod numeric;

use api::parse;

use eval::context_item::ContextItem;
use eval::eval_context::EvalContext;
use eval::built_in_function::BuiltInFunction;

use prelude::numeric::define_math;

pub fn setup_prelude(context: &mut EvalContext) {
    define_math(context);
}

pub fn define_built_in(
    context: &mut EvalContext,
    name: &str,
    params: usize,
    function: BuiltInFunction,
) {
    let item = ContextItem::built_in_defaults(function, params);
    context.set(name, item);
}

pub fn apply_program(context: &mut EvalContext, string: &str) {
    let prog = parse(string).expect("Parse error");

    for statement in prog {
        context.apply(statement).expect("Failed to apply prelude program");
    }
}

<|endoftext|>