<commit_before>#[macro_use] extern crate log;
extern crate env_logger;
extern crate docopt;
extern crate libc;
extern crate rand;
extern crate rustc_serialize;

#[macro_use]
extern crate error_chain;

use docopt::Docopt;
use rand::{Rng, SeedableRng, XorShiftRng};
use rustc_serialize::{Decodable, Decoder};
use std::mem;
use std::slice;

mod area;
mod c;
mod flash;
pub mod api;
mod pdump;

use flash::Flash;
use area::{AreaDesc, FlashId};

const USAGE: &'static str = "
Mcuboot simulator

Usage:
  bootsim sizes
  bootsim run --device TYPE [--align SIZE]
  bootsim (--help | --version)

Options:
  -h, --help         Show this message
  --version          Version
  --device TYPE      MCU to simulate
                     Valid values: stm32f4, k64f
  --align SIZE       Flash write alignment
";

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_help: bool,
    flag_version: bool,
    flag_device: Option<DeviceName>,
    flag_align: Option<AlignArg>,
    cmd_sizes: bool,
    cmd_run: bool,
}

#[derive(Debug, RustcDecodable)]
enum DeviceName { Stm32f4, K64f, K64fBig }

#[derive(Debug)]
struct AlignArg(u8);

impl Decodable for AlignArg {
    // Decode the alignment ourselves, to restrict it to the valid possible alignments.
    fn decode<D: Decoder>(d: &mut D) -> Result<AlignArg, D::Error> {
        let m = d.read_u8()?;
        match m {
            1 | 2 | 4 | 8 => Ok(AlignArg(m)),
            _ => Err(d.error("Invalid alignment")),
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // println!("args: {:#?}", args);

    if args.cmd_sizes {
        show_sizes();
        return;
    }

    let align = args.flag_align.map(|x| x.0).unwrap_or(1);

    let (mut flash, areadesc) = match args.flag_device {
        None => panic!("Missing mandatory argument"),
        Some(DeviceName::Stm32f4) => {
            // STM style flash.  Large sectors, with a large scratch area.
            let flash = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
                                   64 * 1024,
                                   128 * 1024, 128 * 1024, 128 * 1024],
                                   align as usize);
            let mut areadesc = AreaDesc::new(&flash);
            areadesc.add_image(0x020000, 0x020000, FlashId::Image0);
            areadesc.add_image(0x040000, 0x020000, FlashId::Image1);
            areadesc.add_image(0x060000, 0x020000, FlashId::ImageScratch);
            (flash, areadesc)
        }
        Some(DeviceName::K64f) => {
            // NXP style flash.  Small sectors, one small sector for scratch.
            let flash = Flash::new(vec![4096; 128], align as usize);

            let mut areadesc = AreaDesc::new(&flash);
            areadesc.add_image(0x020000, 0x020000, FlashId::Image0);
            areadesc.add_image(0x040000, 0x020000, FlashId::Image1);
            areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch);
            (flash, areadesc)
        }
        Some(DeviceName::K64fBig) => {
            // Simulating an STM style flash on top of an NXP style flash.  Underlying flash device
            // uses small sectors, but we tell the bootloader they are large.
            let flash = Flash::new(vec![4096; 128], align as usize);

            let mut areadesc = AreaDesc::new(&flash);
            areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0);
            areadesc.add_simple_image(0x040000, 0x020000, FlashId::Image1);
            areadesc.add_simple_image(0x060000, 0x020000, FlashId::ImageScratch);
            (flash, areadesc)
        }
    };

    // println!("Areas: {:#?}", areadesc.get_c());

    // Install the boot trailer signature, so that the code will start an upgrade.
    let primary = install_image(&mut flash, 0x020000, 32779);

    // Install an upgrade image.
    let upgrade = install_image(&mut flash, 0x040000, 41922);

    // Set an alignment, and position the magic value.
    c::set_sim_flash_align(align);
    let trailer_size = c::boot_trailer_sz();

    // Mark the upgrade as ready to install.  (This looks like it might be a bug in the code,
    // however.)
    mark_upgrade(&mut flash, 0x060000 - trailer_size as usize);

    let (fl2, total_count) = try_upgrade(&flash, &areadesc, None);
    info!("First boot, count={}", total_count);
    assert!(verify_image(&fl2, 0x020000, &upgrade));

    let mut bad = 0;
    // Let's try an image halfway through.
    for i in 1 .. total_count {
        info!("Try interruption at {}", i);
        let (fl3, total_count) = try_upgrade(&flash, &areadesc, Some(i));
        info!("Second boot, count={}", total_count);
        if !verify_image(&fl3, 0x020000, &upgrade) {
            warn!("FAIL at step {} of {}", i, total_count);
            bad += 1;
        }
        if !verify_image(&fl3, 0x040000, &primary) {
            warn!("Slot 1 FAIL at step {} of {}", i, total_count);
            bad += 1;
        }
    }
    error!("{} out of {} failed {:.2}%",
           bad, total_count,
           bad as f32 * 100.0 / total_count as f32);

    for count in 2 .. 5 {
        info!("Try revert: {}", count);
        let fl2 = try_revert(&flash, &areadesc, count);
        assert!(verify_image(&fl2, 0x020000, &primary));
    }

    info!("Try norevert");
    let fl2 = try_norevert(&flash, &areadesc);
    assert!(verify_image(&fl2, 0x020000, &upgrade));

    /*
    // show_flash(&flash);

    println!("First boot for upgrade");
    // c::set_flash_counter(570);
    c::boot_go(&mut flash, &areadesc);
    // println!("{} flash ops", c::get_flash_counter());

    verify_image(&flash, 0x020000, &upgrade);

    println!("\n------------------\nSecond boot");
    c::boot_go(&mut flash, &areadesc);
    */
}

/// Test a boot, optionally stopping after 'n' flash options.  Returns a count of the number of
/// flash operations done total.
fn try_upgrade(flash: &Flash, areadesc: &AreaDesc, stop: Option<i32>) -> (Flash, i32) {
    // Clone the flash to have a new copy.
    let mut fl = flash.clone();

    c::set_flash_counter(stop.unwrap_or(0));
    let (first_interrupted, cnt1) = match c::boot_go(&mut fl, &areadesc) {
        -0x13579 => (true, stop.unwrap()),
        0 => (false, -c::get_flash_counter()),
        x => panic!("Unknown return: {}", x),
    };
    c::set_flash_counter(0);

    if first_interrupted {
        // fl.dump();
        match c::boot_go(&mut fl, &areadesc) {
            -0x13579 => panic!("Shouldn't stop again"),
            0 => (),
            x => panic!("Unknown return: {}", x),
        }
    }

    let cnt2 = cnt1 - c::get_flash_counter();

    (fl, cnt2)
}

fn try_revert(flash: &Flash, areadesc: &AreaDesc, count: usize) -> Flash {
    let mut fl = flash.clone();
    c::set_flash_counter(0);

    for _ in 0 .. count {
        assert_eq!(c::boot_go(&mut fl, &areadesc), 0);
    }
    fl
}

fn try_norevert(flash: &Flash, areadesc: &AreaDesc) -> Flash {
    let mut fl = flash.clone();
    c::set_flash_counter(0);
    let align = c::get_sim_flash_align() as usize;

    assert_eq!(c::boot_go(&mut fl, &areadesc), 0);
    // Write boot_ok
    fl.write(0x040000 - align, &[1]).unwrap();
    assert_eq!(c::boot_go(&mut fl, &areadesc), 0);
    fl
}

/// Show the flash layout.
#[allow(dead_code)]
fn show_flash(flash: &Flash) {
    println!("---- Flash configuration ----");
    for sector in flash.sector_iter() {
        println!("    {:2}: 0x{:08x}, 0x{:08x}",
                 sector.num, sector.base, sector.size);
    }
    println!("");
}

/// Install a "program" into the given image.  This fakes the image header, or at least all of the
/// fields used by the given code.  Returns a copy of the image that was written.
fn install_image(flash: &mut Flash, offset: usize, len: usize) -> Vec<u8> {
    let offset0 = offset;

    // Generate a boot header.  Note that the size doesn't include the header.
    let header = ImageHeader {
        magic: 0x96f3b83c,
        tlv_size: 0,
        _pad1: 0,
        hdr_size: 32,
        key_id: 0,
        _pad2: 0,
        img_size: len as u32,
        flags: 0,
        ver: ImageVersion {
            major: 1,
            minor: 0,
            revision: 1,
            build_num: 1,
        },
        _pad3: 0,
    };

    let b_header = header.as_raw();
    /*
    let b_header = unsafe { slice::from_raw_parts(&header as *const _ as *const u8,
                                                  mem::size_of::<ImageHeader>()) };
                                                  */
    assert_eq!(b_header.len(), 32);
    flash.write(offset, &b_header).unwrap();
    let offset = offset + b_header.len();

    // The core of the image itself is just pseudorandom data.
    let mut buf = vec![0; len];
    splat(&mut buf, offset);
    flash.write(offset, &buf).unwrap();
    let offset = offset + buf.len();

    // Copy out the image so that we can verify that the image was installed correctly later.
    let mut copy = vec![0u8; offset - offset0];
    flash.read(offset0, &mut copy).unwrap();

    copy
}

/// Verify that given image is present in the flash at the given offset.
fn verify_image(flash: &Flash, offset: usize, buf: &[u8]) -> bool {
    let mut copy = vec![0u8; buf.len()];
    flash.read(offset, &mut copy).unwrap();

    if buf != &copy[..] {
        for i in 0 .. buf.len() {
            if buf[i] != copy[i] {
                info!("First failure at {:#x}", offset + i);
                break;
            }
        }
        false
    } else {
        true
    }
}

/// The image header
#[repr(C)]
pub struct ImageHeader {
    magic: u32,
    tlv_size: u16,
    key_id: u8,
    _pad1: u8,
    hdr_size: u16,
    _pad2: u16,
    img_size: u32,
    flags: u32,
    ver: ImageVersion,
    _pad3: u32,
}

impl AsRaw for ImageHeader {}

#[repr(C)]
pub struct ImageVersion {
    major: u8,
    minor: u8,
    revision: u16,
    build_num: u32,
}

/// Write out the magic so that the loader tries doing an upgrade.
fn mark_upgrade(flash: &mut Flash, offset: usize) {
    let magic = vec![0x77, 0xc2, 0x95, 0xf3,
                     0x60, 0xd2, 0xef, 0x7f,
                     0x35, 0x52, 0x50, 0x0f,
                     0x2c, 0xb6, 0x79, 0x80];
    flash.write(offset, &magic).unwrap();
}

// Drop some pseudo-random gibberish onto the data.
fn splat(data: &mut [u8], seed: usize) {
    let seed_block = [0x135782ea, 0x92184728, data.len() as u32, seed as u32];
    let mut rng: XorShiftRng = SeedableRng::from_seed(seed_block);
    rng.fill_bytes(data);
}

/// Return a read-only view into the raw bytes of this object
trait AsRaw : Sized {
    fn as_raw<'a>(&'a self) -> &'a [u8] {
        unsafe { slice::from_raw_parts(self as *const _ as *const u8,
                                       mem::size_of::<Self>()) }
    }
}

fn show_sizes() {
    // This isn't panic safe.
    let old_align = c::get_sim_flash_align();
    for min in &[1, 2, 4, 8] {
        c::set_sim_flash_align(*min);
        let msize = c::boot_trailer_sz();
        println!("{:2}: {} (0x{:x})", min, msize, msize);
    }
    c::set_sim_flash_align(old_align);
}
<commit_msg>sim: pad images to alignment<commit_after>#[macro_use] extern crate log;
extern crate env_logger;
extern crate docopt;
extern crate libc;
extern crate rand;
extern crate rustc_serialize;

#[macro_use]
extern crate error_chain;

use docopt::Docopt;
use rand::{Rng, SeedableRng, XorShiftRng};
use rustc_serialize::{Decodable, Decoder};
use std::mem;
use std::slice;

mod area;
mod c;
mod flash;
pub mod api;
mod pdump;

use flash::Flash;
use area::{AreaDesc, FlashId};

const USAGE: &'static str = "
Mcuboot simulator

Usage:
  bootsim sizes
  bootsim run --device TYPE [--align SIZE]
  bootsim (--help | --version)

Options:
  -h, --help         Show this message
  --version          Version
  --device TYPE      MCU to simulate
                     Valid values: stm32f4, k64f
  --align SIZE       Flash write alignment
";

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_help: bool,
    flag_version: bool,
    flag_device: Option<DeviceName>,
    flag_align: Option<AlignArg>,
    cmd_sizes: bool,
    cmd_run: bool,
}

#[derive(Debug, RustcDecodable)]
enum DeviceName { Stm32f4, K64f, K64fBig }

#[derive(Debug)]
struct AlignArg(u8);

impl Decodable for AlignArg {
    // Decode the alignment ourselves, to restrict it to the valid possible alignments.
    fn decode<D: Decoder>(d: &mut D) -> Result<AlignArg, D::Error> {
        let m = d.read_u8()?;
        match m {
            1 | 2 | 4 | 8 => Ok(AlignArg(m)),
            _ => Err(d.error("Invalid alignment")),
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // println!("args: {:#?}", args);

    if args.cmd_sizes {
        show_sizes();
        return;
    }

    let align = args.flag_align.map(|x| x.0).unwrap_or(1);

    let (mut flash, areadesc) = match args.flag_device {
        None => panic!("Missing mandatory argument"),
        Some(DeviceName::Stm32f4) => {
            // STM style flash.  Large sectors, with a large scratch area.
            let flash = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
                                   64 * 1024,
                                   128 * 1024, 128 * 1024, 128 * 1024],
                                   align as usize);
            let mut areadesc = AreaDesc::new(&flash);
            areadesc.add_image(0x020000, 0x020000, FlashId::Image0);
            areadesc.add_image(0x040000, 0x020000, FlashId::Image1);
            areadesc.add_image(0x060000, 0x020000, FlashId::ImageScratch);
            (flash, areadesc)
        }
        Some(DeviceName::K64f) => {
            // NXP style flash.  Small sectors, one small sector for scratch.
            let flash = Flash::new(vec![4096; 128], align as usize);

            let mut areadesc = AreaDesc::new(&flash);
            areadesc.add_image(0x020000, 0x020000, FlashId::Image0);
            areadesc.add_image(0x040000, 0x020000, FlashId::Image1);
            areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch);
            (flash, areadesc)
        }
        Some(DeviceName::K64fBig) => {
            // Simulating an STM style flash on top of an NXP style flash.  Underlying flash device
            // uses small sectors, but we tell the bootloader they are large.
            let flash = Flash::new(vec![4096; 128], align as usize);

            let mut areadesc = AreaDesc::new(&flash);
            areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0);
            areadesc.add_simple_image(0x040000, 0x020000, FlashId::Image1);
            areadesc.add_simple_image(0x060000, 0x020000, FlashId::ImageScratch);
            (flash, areadesc)
        }
    };

    // println!("Areas: {:#?}", areadesc.get_c());

    // Install the boot trailer signature, so that the code will start an upgrade.
    // TODO: This must be a multiple of flash alignment, add support for an image that is smaller,
    // and just gets padded.
    let primary = install_image(&mut flash, 0x020000, 32784);

    // Install an upgrade image.
    let upgrade = install_image(&mut flash, 0x040000, 41928);

    // Set an alignment, and position the magic value.
    c::set_sim_flash_align(align);
    let trailer_size = c::boot_trailer_sz();

    // Mark the upgrade as ready to install.  (This looks like it might be a bug in the code,
    // however.)
    mark_upgrade(&mut flash, 0x060000 - trailer_size as usize);

    let (fl2, total_count) = try_upgrade(&flash, &areadesc, None);
    info!("First boot, count={}", total_count);
    assert!(verify_image(&fl2, 0x020000, &upgrade));

    let mut bad = 0;
    // Let's try an image halfway through.
    for i in 1 .. total_count {
        info!("Try interruption at {}", i);
        let (fl3, total_count) = try_upgrade(&flash, &areadesc, Some(i));
        info!("Second boot, count={}", total_count);
        if !verify_image(&fl3, 0x020000, &upgrade) {
            warn!("FAIL at step {} of {}", i, total_count);
            bad += 1;
        }
        if !verify_image(&fl3, 0x040000, &primary) {
            warn!("Slot 1 FAIL at step {} of {}", i, total_count);
            bad += 1;
        }
    }
    error!("{} out of {} failed {:.2}%",
           bad, total_count,
           bad as f32 * 100.0 / total_count as f32);

    for count in 2 .. 5 {
        info!("Try revert: {}", count);
        let fl2 = try_revert(&flash, &areadesc, count);
        assert!(verify_image(&fl2, 0x020000, &primary));
    }

    info!("Try norevert");
    let fl2 = try_norevert(&flash, &areadesc);
    assert!(verify_image(&fl2, 0x020000, &upgrade));

    /*
    // show_flash(&flash);

    println!("First boot for upgrade");
    // c::set_flash_counter(570);
    c::boot_go(&mut flash, &areadesc);
    // println!("{} flash ops", c::get_flash_counter());

    verify_image(&flash, 0x020000, &upgrade);

    println!("\n------------------\nSecond boot");
    c::boot_go(&mut flash, &areadesc);
    */
}

/// Test a boot, optionally stopping after 'n' flash options.  Returns a count of the number of
/// flash operations done total.
fn try_upgrade(flash: &Flash, areadesc: &AreaDesc, stop: Option<i32>) -> (Flash, i32) {
    // Clone the flash to have a new copy.
    let mut fl = flash.clone();

    c::set_flash_counter(stop.unwrap_or(0));
    let (first_interrupted, cnt1) = match c::boot_go(&mut fl, &areadesc) {
        -0x13579 => (true, stop.unwrap()),
        0 => (false, -c::get_flash_counter()),
        x => panic!("Unknown return: {}", x),
    };
    c::set_flash_counter(0);

    if first_interrupted {
        // fl.dump();
        match c::boot_go(&mut fl, &areadesc) {
            -0x13579 => panic!("Shouldn't stop again"),
            0 => (),
            x => panic!("Unknown return: {}", x),
        }
    }

    let cnt2 = cnt1 - c::get_flash_counter();

    (fl, cnt2)
}

fn try_revert(flash: &Flash, areadesc: &AreaDesc, count: usize) -> Flash {
    let mut fl = flash.clone();
    c::set_flash_counter(0);

    for _ in 0 .. count {
        assert_eq!(c::boot_go(&mut fl, &areadesc), 0);
    }
    fl
}

fn try_norevert(flash: &Flash, areadesc: &AreaDesc) -> Flash {
    let mut fl = flash.clone();
    c::set_flash_counter(0);
    let align = c::get_sim_flash_align() as usize;

    assert_eq!(c::boot_go(&mut fl, &areadesc), 0);
    // Write boot_ok
    fl.write(0x040000 - align, &[1]).unwrap();
    assert_eq!(c::boot_go(&mut fl, &areadesc), 0);
    fl
}

/// Show the flash layout.
#[allow(dead_code)]
fn show_flash(flash: &Flash) {
    println!("---- Flash configuration ----");
    for sector in flash.sector_iter() {
        println!("    {:2}: 0x{:08x}, 0x{:08x}",
                 sector.num, sector.base, sector.size);
    }
    println!("");
}

/// Install a "program" into the given image.  This fakes the image header, or at least all of the
/// fields used by the given code.  Returns a copy of the image that was written.
fn install_image(flash: &mut Flash, offset: usize, len: usize) -> Vec<u8> {
    let offset0 = offset;

    // Generate a boot header.  Note that the size doesn't include the header.
    let header = ImageHeader {
        magic: 0x96f3b83c,
        tlv_size: 0,
        _pad1: 0,
        hdr_size: 32,
        key_id: 0,
        _pad2: 0,
        img_size: len as u32,
        flags: 0,
        ver: ImageVersion {
            major: 1,
            minor: 0,
            revision: 1,
            build_num: 1,
        },
        _pad3: 0,
    };

    let b_header = header.as_raw();
    /*
    let b_header = unsafe { slice::from_raw_parts(&header as *const _ as *const u8,
                                                  mem::size_of::<ImageHeader>()) };
                                                  */
    assert_eq!(b_header.len(), 32);
    flash.write(offset, &b_header).unwrap();
    let offset = offset + b_header.len();

    // The core of the image itself is just pseudorandom data.
    let mut buf = vec![0; len];
    splat(&mut buf, offset);
    flash.write(offset, &buf).unwrap();
    let offset = offset + buf.len();

    // Copy out the image so that we can verify that the image was installed correctly later.
    let mut copy = vec![0u8; offset - offset0];
    flash.read(offset0, &mut copy).unwrap();

    copy
}

/// Verify that given image is present in the flash at the given offset.
fn verify_image(flash: &Flash, offset: usize, buf: &[u8]) -> bool {
    let mut copy = vec![0u8; buf.len()];
    flash.read(offset, &mut copy).unwrap();

    if buf != &copy[..] {
        for i in 0 .. buf.len() {
            if buf[i] != copy[i] {
                info!("First failure at {:#x}", offset + i);
                break;
            }
        }
        false
    } else {
        true
    }
}

/// The image header
#[repr(C)]
pub struct ImageHeader {
    magic: u32,
    tlv_size: u16,
    key_id: u8,
    _pad1: u8,
    hdr_size: u16,
    _pad2: u16,
    img_size: u32,
    flags: u32,
    ver: ImageVersion,
    _pad3: u32,
}

impl AsRaw for ImageHeader {}

#[repr(C)]
pub struct ImageVersion {
    major: u8,
    minor: u8,
    revision: u16,
    build_num: u32,
}

/// Write out the magic so that the loader tries doing an upgrade.
fn mark_upgrade(flash: &mut Flash, offset: usize) {
    let magic = vec![0x77, 0xc2, 0x95, 0xf3,
                     0x60, 0xd2, 0xef, 0x7f,
                     0x35, 0x52, 0x50, 0x0f,
                     0x2c, 0xb6, 0x79, 0x80];
    flash.write(offset, &magic).unwrap();
}

// Drop some pseudo-random gibberish onto the data.
fn splat(data: &mut [u8], seed: usize) {
    let seed_block = [0x135782ea, 0x92184728, data.len() as u32, seed as u32];
    let mut rng: XorShiftRng = SeedableRng::from_seed(seed_block);
    rng.fill_bytes(data);
}

/// Return a read-only view into the raw bytes of this object
trait AsRaw : Sized {
    fn as_raw<'a>(&'a self) -> &'a [u8] {
        unsafe { slice::from_raw_parts(self as *const _ as *const u8,
                                       mem::size_of::<Self>()) }
    }
}

fn show_sizes() {
    // This isn't panic safe.
    let old_align = c::get_sim_flash_align();
    for min in &[1, 2, 4, 8] {
        c::set_sim_flash_align(*min);
        let msize = c::boot_trailer_sz();
        println!("{:2}: {} (0x{:x})", min, msize, msize);
    }
    c::set_sim_flash_align(old_align);
}
<|endoftext|>


<commit_before>//! Items Entity

mod path;
mod kind;
mod item;
mod content;

use std::collections::BTreeMap;
use hyper::method::Method;
use serde_json::{self, Value};
use ::connection::{Connection, Helper};
use ::odata::Parameters;
use ::api::MultiOption;
use ::{Result, Error};

pub use self::path::Path;
pub use self::kind::Kind;
pub use self::item::Item;
pub use self::content::Content;

/// Items Entity implementation.
///
/// Items struct implemets methods of [Items API Entity](http://api.sharefile.com/rest/docs/resource.aspx?name=Items)
pub struct Items {
	conn: Connection,
	meta: bool,
}

impl Items {
	/// Create a new instance of Item Entities API
	pub fn new(conn: Connection) -> Self {
		Items {
			conn: conn,
			meta: false,
		}
	}

	/// Set the flag to inform all future API requests to include item meta information
	/// or omit it.
	pub fn include_meta(&mut self, include: bool) {
		self.meta = include;
	}

	/// Resolve given `path` to the Item ID. On success returns `Some(Path::Id(id))`
	// and None otherwise.
	pub fn resolve_path(&self, path: Path) -> Option<Path> {
		if let &Path::Id(_) = &path {
			// The path is the ID already
			Some(path)
		}
		else {
			// Resolve the path to the ID
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Some(item.path()),
				_ => None
			}
		}
	}

	/// Search for Item(s) at the `path` given and return found. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn stat(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		self.query_items(path.entity_and_parameters(None, parameters))
	}

	/// List all items at the `path` given. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn list(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		match self.stat(path, None) {
			Ok(MultiOption::One(item)) => match item.kind {
				Kind::Folder => {
					self.query_items(item.path().entity_and_parameters(Some("/Children"), parameters))
				},
				Kind::File => {
					Ok(MultiOption::One(item))
				}
			},
			Ok(other) => Ok(other),
			Err(err) => err.result()
		}
	}

	/// Create folder with `parent` item and `name` given. On success returns the path with the ID
	/// of the folder created.
	pub fn create_folder<T>(&self, parent: Path, name: T, description: Option<T>, overwite: bool) -> Result<Path>
	where T: Into<String> {
		if let Some(path) = self.resolve_path(parent) {
			// Prepare folder details
			let mut data = BTreeMap::new();
			data.insert(String::from("Name"), Value::String(name.into()));

			if let Some(desc) = description {
				data.insert(String::from("Description"), Value::String(desc.into()));
			}

			let body = Value::Object(data);

			// Create folder
			let parameters = Parameters::new()
				.custom(vec![("overwite", super::bool_to_string(overwite)), ("passthrough", String::from("false"))]);

			let url = path.entity_and_parameters(Some("/Folder"), Some(parameters));

			self.query_create(url, Some(body))
				.and_then(|r| Error::from_json(r))
				.and_then(|v| Path::from_json(v))
		}
		else {
			Error::new("Cannot resolve parent ID").result()
		}
	}

	/// Download the item identified by `path`. The method returns reader which can be used
	/// to read data in any convenient manner.
	///
	/// The snippet of how the remote file can be downloaded to local.
	///
	/// ```ignore
	/// // Lets assume we have the opened connection already
	/// let path = Path::Absolute("/my_folder/remote_file.txt");
	///	let mut stream = conn.items().download(path).unwrap();
	/// let mut file = File::create("local_file.txt").unwrap();
	/// let mut buf = [0; 1024];
	/// loop {
	/// 	match stream.read(&mut buf) {
	///			Ok(0) => break, // Zero bytes mean the end of file
	///			Ok(n) => file.write_all(&buf[0..n]).unwrap(),
	///			Err(err) => panic!("{:?}", err)
	///		};
	///	}
	/// ```
	pub fn download(&self, path: Path) -> Result<Content> {
		if let Path::Id(id) = path {
			// We have the ID alredy so just start download
			Content::open_for_read(self.conn.clone(), id)
		}
		else {
			// We have a path which should be resolved to the id first
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Content::open_for_read(self.conn.clone(), item.id),
				Ok(MultiOption::Many(_)) => Error::new("There are more than one Item on path").result(),
				Ok(MultiOption::None) => Error::new("The Item is not found").result(),
				Err(err) => err.result()
			}
		}
	}

	// Do API request which creates new Items (POST)
	fn query_create(&self, uri: String, data: Option<Value>) -> Result<Value> {
		let body = match data {
			Some(ref value) => Some(serde_json::to_string(value).unwrap()),
			None => None
		};

		match self.conn.query_string(Method::Post, uri, Some(Helper::json_headers()), body) {
			Ok(ref json) => match serde_json::from_str(json) {
				Ok(data) => Ok(data),
				Err(err) => Error::new("JSON parse failed").because(err).result()
			},
			Err(err) => err.result()
		}
	}

	// Do API request which returns Item Collection (GET)
	fn query_items(&self, uri: String) -> Result<MultiOption<Item>> {
		match self.conn.query_string(Method::Get, uri, None, None) {
			Ok(ref json) => match serde_json::from_str(json) {
				Ok(data) => Item::from_value(data, self.meta),
				Err(err) => Error::new("JSON parse failed").because(err).result()
			},
			Err(err) => err.result()
		}
	}
}
<commit_msg>Fix typo in overwrite<commit_after>//! Items Entity

mod path;
mod kind;
mod item;
mod content;

use std::collections::BTreeMap;
use hyper::method::Method;
use serde_json::{self, Value};
use ::connection::{Connection, Helper};
use ::odata::Parameters;
use ::api::MultiOption;
use ::{Result, Error};

pub use self::path::Path;
pub use self::kind::Kind;
pub use self::item::Item;
pub use self::content::Content;

/// Items Entity implementation.
///
/// Items struct implemets methods of [Items API Entity](http://api.sharefile.com/rest/docs/resource.aspx?name=Items)
pub struct Items {
	conn: Connection,
	meta: bool,
}

impl Items {
	/// Create a new instance of Item Entities API
	pub fn new(conn: Connection) -> Self {
		Items {
			conn: conn,
			meta: false,
		}
	}

	/// Set the flag to inform all future API requests to include item meta information
	/// or omit it.
	pub fn include_meta(&mut self, include: bool) {
		self.meta = include;
	}

	/// Resolve given `path` to the Item ID. On success returns `Some(Path::Id(id))`
	// and None otherwise.
	pub fn resolve_path(&self, path: Path) -> Option<Path> {
		if let &Path::Id(_) = &path {
			// The path is the ID already
			Some(path)
		}
		else {
			// Resolve the path to the ID
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Some(item.path()),
				_ => None
			}
		}
	}

	/// Search for Item(s) at the `path` given and return found. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn stat(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		self.query_items(path.entity_and_parameters(None, parameters))
	}

	/// List all items at the `path` given. `parameters` can be used
	/// to provide additional options to the API request, like `includeDeleted`.
	pub fn list(&self, path: Path, parameters: Option<Parameters>) -> Result<MultiOption<Item>> {
		match self.stat(path, None) {
			Ok(MultiOption::One(item)) => match item.kind {
				Kind::Folder => {
					self.query_items(item.path().entity_and_parameters(Some("/Children"), parameters))
				},
				Kind::File => {
					Ok(MultiOption::One(item))
				}
			},
			Ok(other) => Ok(other),
			Err(err) => err.result()
		}
	}

	/// Create folder with `parent` item and `name` given. On success returns the path with the ID
	/// of the folder created.
	pub fn create_folder<T>(&self, parent: Path, name: T, description: Option<T>, overwite: bool) -> Result<Path>
	where T: Into<String> {
		if let Some(path) = self.resolve_path(parent) {
			// Prepare folder details
			let mut data = BTreeMap::new();
			data.insert(String::from("Name"), Value::String(name.into()));

			if let Some(desc) = description {
				data.insert(String::from("Description"), Value::String(desc.into()));
			}

			let body = Value::Object(data);

			// Create folder
			let parameters = Parameters::new()
				.custom(vec![("overwrite", super::bool_to_string(overwite)), ("passthrough", String::from("false"))]);

			let url = path.entity_and_parameters(Some("/Folder"), Some(parameters));

			self.query_create(url, Some(body))
				.and_then(|r| Error::from_json(r))
				.and_then(|v| Path::from_json(v))
		}
		else {
			Error::new("Cannot resolve parent ID").result()
		}
	}

	/// Download the item identified by `path`. The method returns reader which can be used
	/// to read data in any convenient manner.
	///
	/// The snippet of how the remote file can be downloaded to local.
	///
	/// ```ignore
	/// // Lets assume we have the opened connection already
	/// let path = Path::Absolute("/my_folder/remote_file.txt");
	///	let mut stream = conn.items().download(path).unwrap();
	/// let mut file = File::create("local_file.txt").unwrap();
	/// let mut buf = [0; 1024];
	/// loop {
	/// 	match stream.read(&mut buf) {
	///			Ok(0) => break, // Zero bytes mean the end of file
	///			Ok(n) => file.write_all(&buf[0..n]).unwrap(),
	///			Err(err) => panic!("{:?}", err)
	///		};
	///	}
	/// ```
	pub fn download(&self, path: Path) -> Result<Content> {
		if let Path::Id(id) = path {
			// We have the ID alredy so just start download
			Content::open_for_read(self.conn.clone(), id)
		}
		else {
			// We have a path which should be resolved to the id first
			match self.stat(path, None) {
				Ok(MultiOption::One(item)) => Content::open_for_read(self.conn.clone(), item.id),
				Ok(MultiOption::Many(_)) => Error::new("There are more than one Item on path").result(),
				Ok(MultiOption::None) => Error::new("The Item is not found").result(),
				Err(err) => err.result()
			}
		}
	}

	// Do API request which creates new Items (POST)
	fn query_create(&self, uri: String, data: Option<Value>) -> Result<Value> {
		let body = match data {
			Some(ref value) => Some(serde_json::to_string(value).unwrap()),
			None => None
		};

		match self.conn.query_string(Method::Post, uri, Some(Helper::json_headers()), body) {
			Ok(ref json) => match serde_json::from_str(json) {
				Ok(data) => Ok(data),
				Err(err) => Error::new("JSON parse failed").because(err).result()
			},
			Err(err) => err.result()
		}
	}

	// Do API request which returns Item Collection (GET)
	fn query_items(&self, uri: String) -> Result<MultiOption<Item>> {
		match self.conn.query_string(Method::Get, uri, None, None) {
			Ok(ref json) => match serde_json::from_str(json) {
				Ok(data) => Item::from_value(data, self.meta),
				Err(err) => Error::new("JSON parse failed").because(err).result()
			},
			Err(err) => err.result()
		}
	}
}
<|endoftext|>


<commit_before>extern crate vk_api;
extern crate xml;

mod crawler;

use xml::EventReader;
use xml::attribute::OwnedAttribute;

use std::os::raw::c_char;
use std::ptr;

pub fn load_xml() {
    let vk_xml = EventReader::new(vk_api::VK_XML);
    // The vulkan registry
    let registry = crawler::crawl(vk_xml.into_iter(), VkRegistry::new(vk_api::VK_XML.len()));
}

pub struct VkRegistry {
    string_buffer: String,
    types: Vec<VkType>
}

impl<'a> VkRegistry {
    fn new(capacity: usize) -> VkRegistry {
        VkRegistry {
            string_buffer: String::with_capacity(capacity),
            types: Vec::with_capacity(256)
        }
    }

    fn push_type(&mut self, vk_type: VkType) -> Result<(), ()> {
        match vk_type {
            VkType::None => Err(()),
            vk_type      => {self.types.push(vk_type); Ok(())}
        }
    }

    /// Append a given attribute to the internal string buffer and return a pointer to a CStr that represents the attribute
    fn append_str(&mut self, string: &str) -> *const c_char {
        // We want to have all of the string in one block of memory in order to save heap allocation time.
        self.string_buffer.push_str(string);
        self.string_buffer.push('\0');

        (self.string_buffer.as_ptr() as usize + self.string_buffer.len() - string.len() - 1) as *const c_char
    }
}

#[derive(Debug)]
enum VkFieldType {
    Var(*const c_char),
    Ptr(*const c_char),
    PtrMut(*const c_char),
    /// Default value to initialize with.
    Unknown
}

#[derive(Debug)]
struct VkField {
    field_type: VkFieldType,
    field_name: *const c_char,
}

impl VkField {
    fn empty() -> VkField {
        VkField {
            field_type: VkFieldType::Unknown,
            field_name: ptr::null()
        }
    }

    fn set_type(&mut self, field_type: *const c_char) {
        use VkFieldType::*;
        match self.field_type {
            Var(ref mut s) |
            Ptr(ref mut s) |
            PtrMut(ref mut s) =>
                if *s == ptr::null() {
                    *s = field_type
                } else {panic!("Field type already set")},
            Unknown => self.field_type = Var(field_type)

        }
    }

    fn change_type_var(&mut self) {
        use VkFieldType::*;
        match self.field_type {
            Var(s) |
            Ptr(s) |
            PtrMut(s) => self.field_type = Var(s),
            Unknown   => self.field_type = Var(ptr::null())
        }
    }

    fn change_type_ptr(&mut self) {
        use VkFieldType::*;
        match self.field_type {
            Var(s) |
            Ptr(s) |
            PtrMut(s) => self.field_type = Ptr(s),
            Unknown   => self.field_type = Ptr(ptr::null())
        }
    }

    fn change_type_ptr_mut(&mut self) {
        use VkFieldType::*;
        match self.field_type {
            Var(s) |
            Ptr(s) |
            PtrMut(s) => self.field_type = PtrMut(s),
            Unknown   => self.field_type = PtrMut(ptr::null())
        }
    }

    fn set_name(&mut self, field_name: *const c_char) {
        if field_name != ptr::null() {
            panic!("Unexpected \"name\" tag");
        } else {
            self.field_name = field_name;
        }
    }
}

/// A variant of a vulkan enum
#[derive(Debug)]
struct VkVariant {
    name: *const c_char,
    value: isize
}

#[derive(Debug)]
enum VkType {
    Struct {
        name: *const c_char,
        fields: Vec<VkField>
    },

    Union {
        name: *const c_char,
        variants: Vec<VkField>
    },

    Enum {
        name: *const c_char,
        variants: Vec<VkVariant>
    },

    BaseType {
        /// The type that is being aliased
        ty: *const c_char,
        /// The name of the new type
        name: *const c_char
    },

    /// A dummy variant used to initialize the type creation system
    None
}<commit_msg>Updated Debug implementation for VkFieldType to print value of stored CStr.<commit_after>extern crate vk_api;
extern crate xml;

mod crawler;

use xml::EventReader;
use xml::attribute::OwnedAttribute;

use std::os::raw::c_char;
use std::ffi::CStr;
use std::ptr;
use std::fmt;

pub fn load_xml() {
    let vk_xml = EventReader::new(vk_api::VK_XML);
    // The vulkan registry
    let registry = crawler::crawl(vk_xml.into_iter(), VkRegistry::new(vk_api::VK_XML.len()));
}

pub struct VkRegistry {
    string_buffer: String,
    types: Vec<VkType>
}

impl<'a> VkRegistry {
    fn new(capacity: usize) -> VkRegistry {
        VkRegistry {
            string_buffer: String::with_capacity(capacity),
            types: Vec::with_capacity(256)
        }
    }

    fn push_type(&mut self, vk_type: VkType) -> Result<(), ()> {
        match vk_type {
            VkType::None => Err(()),
            vk_type      => {self.types.push(vk_type); Ok(())}
        }
    }

    /// Append a given attribute to the internal string buffer and return a pointer to a CStr that represents the attribute
    fn append_str(&mut self, string: &str) -> *const c_char {
        // We want to have all of the string in one block of memory in order to save heap allocation time.
        self.string_buffer.push_str(string);
        self.string_buffer.push('\0');

        (self.string_buffer.as_ptr() as usize + self.string_buffer.len() - string.len() - 1) as *const c_char
    }
}

enum VkFieldType {
    Var(*const c_char),
    Ptr(*const c_char),
    PtrMut(*const c_char),
    /// Default value to initialize with.
    Unknown
}

impl fmt::Debug for VkFieldType {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        use VkFieldType::*;
        if let Unknown = *self {
            write!(fmt, "Unknown")
        } else {
            let pt;
            fmt.debug_tuple(
                match *self {
                    Var(p) => {pt = p; "Var"}
                    Ptr(p) => {pt = p; "Ptr"}
                    PtrMut(p) => {pt = p; "PtrMut"}
                    Unknown => unreachable!()
                })
                .field(unsafe{ &if pt != ptr::null() {CStr::from_ptr(pt).to_str().unwrap()} else {"Error: Null Ptr"} })
                .finish()
        }
    }
}

#[derive(Debug)]
struct VkField {
    field_type: VkFieldType,
    field_name: *const c_char,
}

impl VkField {
    fn empty() -> VkField {
        VkField {
            field_type: VkFieldType::Unknown,
            field_name: ptr::null()
        }
    }

    fn set_type(&mut self, field_type: *const c_char) {
        use VkFieldType::*;
        match self.field_type {
            Var(ref mut s) |
            Ptr(ref mut s) |
            PtrMut(ref mut s) =>
                if *s == ptr::null() {
                    *s = field_type
                } else {panic!("Field type already set")},
            Unknown => self.field_type = Var(field_type)

        }
    }

    fn change_type_var(&mut self) {
        use VkFieldType::*;
        match self.field_type {
            Var(s) |
            Ptr(s) |
            PtrMut(s) => self.field_type = Var(s),
            Unknown   => self.field_type = Var(ptr::null())
        }
    }

    fn change_type_ptr(&mut self) {
        use VkFieldType::*;
        match self.field_type {
            Var(s) |
            Ptr(s) |
            PtrMut(s) => self.field_type = Ptr(s),
            Unknown   => self.field_type = Ptr(ptr::null())
        }
    }

    fn change_type_ptr_mut(&mut self) {
        use VkFieldType::*;
        match self.field_type {
            Var(s) |
            Ptr(s) |
            PtrMut(s) => self.field_type = PtrMut(s),
            Unknown   => self.field_type = PtrMut(ptr::null())
        }
    }

    fn set_name(&mut self, field_name: *const c_char) {
        if field_name != ptr::null() {
            panic!("Unexpected \"name\" tag");
        } else {
            self.field_name = field_name;
        }
    }
}

/// A variant of a vulkan enum
#[derive(Debug)]
struct VkVariant {
    name: *const c_char,
    value: isize
}

#[derive(Debug)]
enum VkType {
    Struct {
        name: *const c_char,
        fields: Vec<VkField>
    },

    Union {
        name: *const c_char,
        variants: Vec<VkField>
    },

    Enum {
        name: *const c_char,
        variants: Vec<VkVariant>
    },

    BaseType {
        /// The type that is being aliased
        ty: *const c_char,
        /// The name of the new type
        name: *const c_char
    },

    /// A dummy variant used to initialize the type creation system
    None
}<|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.

#[macro_escape];

// Some basic logging
macro_rules! rtdebug (
    ($( $arg:expr),+) => ( {
        dumb_println(fmt!( $($arg),+ ));

        fn dumb_println(s: &str) {
            use io::WriterUtil;
            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
            dbg.write_str(s);
            dbg.write_str("\n");
        }

    } )
)

// An alternate version with no output, for turning off logging
macro_rules! rtdebug_ (
    ($( $arg:expr),+) => ( $(let _ = $arg)*; )
)

macro_rules! rtassert (
    ( $arg:expr ) => ( {
        if !$arg {
            abort!("assertion failed: %s", stringify!($arg));
        }
    } )
)

macro_rules! abort(
    ($( $msg:expr),+) => ( {
        rtdebug!($($msg),+);

        unsafe { ::libc::abort(); }
    } )
)
<commit_msg>rtdebug off<commit_after>// 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.

#[macro_escape];

// Some basic logging
macro_rules! rtdebug_ (
    ($( $arg:expr),+) => ( {
        dumb_println(fmt!( $($arg),+ ));

        fn dumb_println(s: &str) {
            use io::WriterUtil;
            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
            dbg.write_str(s);
            dbg.write_str("\n");
        }

    } )
)

// An alternate version with no output, for turning off logging
macro_rules! rtdebug (
    ($( $arg:expr),+) => ( $(let _ = $arg)*; )
)

macro_rules! rtassert (
    ( $arg:expr ) => ( {
        if !$arg {
            abort!("assertion failed: %s", stringify!($arg));
        }
    } )
)

macro_rules! abort(
    ($( $msg:expr),+) => ( {
        rtdebug!($($msg),+);

        unsafe { ::libc::abort(); }
    } )
)
<|endoftext|>


<commit_before>use core::pin::Pin;
use futures_core::future::Future;
use futures_core::stream::{Stream, FusedStream};
use futures_core::task::{Context, Poll};
use pin_project::pin_project;

/// Creates a stream of a single element.
///
/// ```
/// # futures::executor::block_on(async {
/// use futures::stream::{self, StreamExt};
///
/// let stream = stream::once(async { 17 });
/// let collected = stream.collect::<Vec<i32>>().await;
/// assert_eq!(collected, vec![17]);
/// # });
/// ```
pub fn once<Fut: Future>(future: Fut) -> Once<Fut> {
    Once::new(future)
}

/// A stream which emits single element and then EOF.
///
/// This stream will never block and is always ready.
#[pin_project]
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Once<Fut> {
    #[pin]
    future: Option<Fut>
}

impl<Fut> Once<Fut> {
    pub(crate) fn new(future: Fut) -> Self {
        Self { future: Some(future) }
    }
}

impl<Fut: Future> Stream for Once<Fut> {
    type Item = Fut::Output;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let mut this = self.project();
        let v = match this.future.as_mut().as_pin_mut() {
            Some(fut) => ready!(fut.poll(cx)),
            None => return Poll::Ready(None),
        };

        this.future.set(None);
        Poll::Ready(Some(v))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.future.is_some() {
            (1, Some(1))
        } else {
            (0, Some(0))
        }
    }
}

impl<Fut: Future> FusedStream for Once<Fut> {
    fn is_terminated(&self) -> bool {
        self.future.is_none()
    }
}
<commit_msg>Remove outdated comment (#2230)<commit_after>use core::pin::Pin;
use futures_core::future::Future;
use futures_core::stream::{Stream, FusedStream};
use futures_core::task::{Context, Poll};
use pin_project::pin_project;

/// Creates a stream of a single element.
///
/// ```
/// # futures::executor::block_on(async {
/// use futures::stream::{self, StreamExt};
///
/// let stream = stream::once(async { 17 });
/// let collected = stream.collect::<Vec<i32>>().await;
/// assert_eq!(collected, vec![17]);
/// # });
/// ```
pub fn once<Fut: Future>(future: Fut) -> Once<Fut> {
    Once::new(future)
}

/// A stream which emits single element and then EOF.
#[pin_project]
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Once<Fut> {
    #[pin]
    future: Option<Fut>
}

impl<Fut> Once<Fut> {
    pub(crate) fn new(future: Fut) -> Self {
        Self { future: Some(future) }
    }
}

impl<Fut: Future> Stream for Once<Fut> {
    type Item = Fut::Output;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let mut this = self.project();
        let v = match this.future.as_mut().as_pin_mut() {
            Some(fut) => ready!(fut.poll(cx)),
            None => return Poll::Ready(None),
        };

        this.future.set(None);
        Poll::Ready(Some(v))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.future.is_some() {
            (1, Some(1))
        } else {
            (0, Some(0))
        }
    }
}

impl<Fut: Future> FusedStream for Once<Fut> {
    fn is_terminated(&self) -> bool {
        self.future.is_none()
    }
}
<|endoftext|>


<commit_before>use std;
use base::*;
use super::{LoudsTrie, NodeID, LoudsPos, LinkID, INVALID_LINK_ID};

struct History<'a> {
    trie_: &'a LoudsTrie,
    node_id_: NodeID,
    louds_pos_: LoudsPos,
    link_id_: LinkID,
    key_pos_: u32,
    //key_id_: u32,
}

impl<'a> History<'a> {
    fn new(trie: &'a LoudsTrie, node_id: NodeID, louds_pos: LoudsPos,
           link_id: LinkID, key_pos: u32) -> History<'a> {
        History { trie_: trie, node_id_: node_id, louds_pos_: louds_pos,
                  link_id_: link_id, key_pos_: key_pos }
    }
}

struct State<'a> {
    history_: Vec<History<'a> >,
    key_buf_: Vec<u8>,
}

impl<'a> State<'a> {
    fn new(trie: &'a LoudsTrie) -> State<'a> {
        let mut out = State { history_: Vec::new(), key_buf_: Vec::new() };
        out.history_.push(History::new(trie, 0, 0, INVALID_LINK_ID, 0));
        out
    }

    fn push<'b>(&mut self, key: &'b[u8], trie: &'a LoudsTrie, node_id: NodeID,
                louds_pos: LoudsPos, link_id: LinkID) {
        self.key_buf_.extend(key);
        assert!(self.key_buf_.len() <= std::u32::MAX as usize);
        self.history_.push(History::new(trie, node_id, louds_pos, link_id,
                                        self.key_buf_.len() as u32));
    }

    fn get_key(&self) -> &[u8] {
        &self.key_buf_[..]
    }

    fn pop(&mut self) -> Option<History<'a> > {
        self.history_.pop()
    }

    fn get_node_id(&self) -> NodeID {
        self.history_.last().unwrap().node_id_
    }

    fn get_link_id(&self) -> LinkID {
        self.history_.last().unwrap().link_id_
    }
}

pub struct Nav<'a> {
    state_: State<'a>,
}

// For lookups, marisa does caching based on the input character.
// We can't do that here. May want to remove or rethink the cache
// implementation in light of this.

impl<'a> Nav<'a> {
    pub fn new(trie: &'a LoudsTrie) -> Nav<'a> {
        Nav { state_: State::new(&trie), }
    }

    fn push(&mut self, node_id: NodeID, louds_pos: LoudsPos) {
        let mut trie = self.state_.history_.last().unwrap().trie_;
        loop {
            if trie.link_flags_.at(node_id.0 as usize) {
                let (node_id, link_id) = trie.get_linked_ids(node_id.0
                                                             as usize);
                // Proceed either to next trie or tail
                match &trie.next_trie_ {
                    &Some(ref next_trie) => {
                        trie = &**next_trie;
                        continue;
                    },
                    &None => {
                        // FIXME: Shouldn't need this temporary vector.
                        //        'restore' should return an iterator, and
                        //        state.push should consume it.
                        let mut v = Vec::new();
                        trie.tail_.restore(node_id.0 as usize, &mut v);

                        // Not sure if these values are correct/useful.
                        // If some stuff is only needed for some nodes...
                        // should reflect that in the types we use
                        self.state_.push(&v, trie, node_id, louds_pos,
                                         link_id);
                    }
                }
            } else {
                let node_char = [ trie.bases_[node_id.0 as usize] ];
                self.state_.push(&node_char, trie, node_id, louds_pos,
                                 INVALID_LINK_ID);
            }
            break;
        }
    }
    pub fn has_child(&self) -> bool {
        self.state_.history_.last().unwrap().trie_.has_child(self.state_.get_node_id())
    }
    pub fn go_to_child(&mut self) -> bool {
        let init_node_id = self.state_.get_node_id();
        if let Some((node_id, louds_pos)) = self.state_.history_.last().unwrap()
                                            .trie_.child_pos(init_node_id) {
            self.push(node_id, louds_pos);
            true
        } else {
            false
        }
    }
    pub fn has_prev_sibling(&self) -> bool {
        // FIXME: Is this all...?
        self.state_.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize - 1)
        }).unwrap_or(false)
    }
    pub fn go_to_prev_sibling(&mut self) -> bool {
        // pop history and string
        // decrease louds_pos and node_id by 1 if we have a sibling
        // get string (factor this out?)
        // push new history & string

        panic!("not implemented")
    }
    pub fn has_sibling(&self) -> bool {
        self.state_.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize + 1)
        }).unwrap_or(false)
    }
    pub fn go_to_sibling(&mut self) -> bool {
        if let Some(h) = self.state_.history_.pop() {
            if h.trie_.louds_.at(h.louds_pos_.0 as usize + 1) {
                // FIXME: What about LinkID?
                self.push(NodeID(h.node_id_.0 + 1),
                          LoudsPos(h.louds_pos_.0 + 1));
                true
            } else {
                false
            }
        } else {
            false
        }
    }
    pub fn has_parent(&self) -> bool {
        panic!("not implemented")
    }
    pub fn go_to_parent(&mut self) -> bool {
        // Could use LOUDS-trie select1(rank0(m)) to navigate upward (within a
        // single trie), but it's probably more efficient just to keep a stack
        // and pop to go up
        self.state_.history_.pop().is_some()
    }
    pub fn is_leaf(&self) -> bool {
        panic!("not implemented")
    }
    //pub fn get_string(&self) -> &str {
    //    panic!("not implemented")
    //}
    pub fn get_u8(&self) -> &[u8] {
        &self.state_.key_buf_[..]
    }
    pub fn is_end(&self) -> bool {
        panic!("not implemented")
    }
}

#[derive(Copy, Clone)]
enum DFT {
    ToChild,
    ToSibling,
    ToParentSibling,
    End
}

impl DFT {
    fn new() -> DFT {
        DFT::ToChild
    }
    fn depth_first_traversal_step<'a>(&mut self, nav: &mut Nav<'a>) -> bool {
        match *self {
            DFT::ToChild => {
                if nav.go_to_child() {
                    return true;
                } else {
                    *self = DFT::ToSibling;
                    return false;
                }
            },
            DFT::ToSibling => {
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                } else {
                    *self = DFT::ToParentSibling;
                    return false;
                }
            },
            DFT::ToParentSibling => {
                if !nav.go_to_parent() {
                    *self = DFT::End;
                    return false;
                }
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                }
                return false;
            },
            DFT::End => {
                return false;
            }
        }
    }
    fn next_terminal<'a, 'b>(&mut self, nav: &'b mut Nav<'a>)
      -> Option<&'b[u8]> {
        loop {
            match *self {
                DFT::End => { return None; },
                _ => (),
            }
            if self.depth_first_traversal_step(nav) {
                return Some(nav.get_u8());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use env_logger;
    use std::cmp::Ordering;
    use quickcheck as qc;
    use config::{Config, NumTries};
    use key::Key;
    use super::{DFT, Nav};
    use super::super::LoudsTrie;

    fn restore_with_nav_prop(v: Vec<String>, num_tries: NumTries)
      -> qc::TestResult {
        if v.iter().any(|x| x.is_empty()) {
            return qc::TestResult::discard();
        }
        let mut keys: Vec<Key> = v.iter().map(|s| Key::new(s.as_bytes()))
                                 .collect();
        let config = Config::new().with_num_tries(num_tries);
        let trie = LoudsTrie::build(&mut keys, &config);

        let mut nav = Nav::new(&trie);
        let mut dft = DFT::new();

        let mut vv1: Vec<Vec<u8>> = v.iter().map(|s| From::from(s.as_bytes()))
                                    .collect();

        let mut vv2: Vec<Vec<u8>> = Vec::new();
        while let Some(s) = dft.next_terminal(&mut nav) {
            vv2.push(From::from(s));
        }

        vv1.sort();
        vv2.sort();
        qc::TestResult::from_bool(vv1.cmp(&vv2) == Ordering::Equal)
        //qc::TestResult::passed()
    }

    #[test]
    fn restore_with_nav_qc() {
        let _ = env_logger::init();
        qc::quickcheck(restore_with_nav_prop as fn(Vec<String>, NumTries)
                       -> qc::TestResult);
    }

    #[test]
    fn restore_with_nav_manual() {
        panic!()

    }
}

<commit_msg>cleanup<commit_after>use std;
use base::*;
use super::{LoudsTrie, NodeID, LoudsPos, LinkID, INVALID_LINK_ID};

struct State<'a> {
    trie_: &'a LoudsTrie,
    node_id_: NodeID,
    louds_pos_: LoudsPos,
    link_id_: LinkID,
    key_pos_: u32,
    //key_id_: u32,
}

impl<'a> State<'a> {
    fn new(trie: &'a LoudsTrie, node_id: NodeID, louds_pos: LoudsPos,
           link_id: LinkID, key_pos: u32) -> State<'a> {
        State { trie_: trie, node_id_: node_id, louds_pos_: louds_pos,
                link_id_: link_id, key_pos_: key_pos }
    }
}

pub struct Nav<'a> {
    history_: Vec<State<'a> >,
    key_buf_: Vec<u8>,
}

// For lookups, marisa does caching based on the input character.
// We can't do that here. May want to remove or rethink the cache
// implementation in light of this.

impl<'a> Nav<'a> {
    fn new(trie: &'a LoudsTrie) -> Nav<'a> {
        let mut out = Nav { history_: Vec::new(), key_buf_: Vec::new() };
        out.history_.push(State::new(trie, NodeID(0), LoudsPos(0),
                          INVALID_LINK_ID, 0));
        out
    }

    fn get_node_id(&self) -> NodeID {
        self.history_.last().unwrap().node_id_
    }

    fn get_link_id(&self) -> LinkID {
        self.history_.last().unwrap().link_id_
    }

    fn push_str<'b>(&mut self, key: &'b[u8], trie: &'a LoudsTrie, node_id: NodeID,
                    louds_pos: LoudsPos, link_id: LinkID) {
        self.key_buf_.extend(key);
        assert!(self.key_buf_.len() <= std::u32::MAX as usize);
        self.history_.push(State::new(trie, node_id, louds_pos, link_id,
                                      self.key_buf_.len() as u32));
    }

    fn push(&mut self, node_id: NodeID, louds_pos: LoudsPos) {
        let mut trie = self.history_.last().unwrap().trie_;
        loop {
            if trie.link_flags_.at(node_id.0 as usize) {
                let (node_id, link_id) = trie.get_linked_ids(node_id.0
                                                             as usize);
                // Proceed either to next trie or tail
                match &trie.next_trie_ {
                    &Some(ref next_trie) => {
                        trie = &**next_trie;
                        continue;
                    },
                    &None => {
                        // FIXME: Shouldn't need this temporary vector.
                        //        'restore' should return an iterator, and
                        //        state.push should consume it.
                        let mut v = Vec::new();
                        trie.tail_.restore(node_id.0 as usize, &mut v);

                        // Not sure if these values are correct/useful.
                        // If some stuff is only needed for some nodes...
                        // should reflect that in the types we use
                        self.push_str(&v, trie, node_id, louds_pos, link_id);
                    }
                }
            } else {
                let node_char = [ trie.bases_[node_id.0 as usize] ];
                self.push_str(&node_char, trie, node_id, louds_pos,
                              INVALID_LINK_ID);
            }
            break;
        }
    }
    pub fn has_child(&self) -> bool {
        self.history_.last().unwrap().trie_.has_child(self.get_node_id())
    }
    pub fn go_to_child(&mut self) -> bool {
        let init_node_id = self.get_node_id();
        if let Some((node_id, louds_pos)) = self.history_.last().unwrap()
                                            .trie_.child_pos(init_node_id) {
            self.push(node_id, louds_pos);
            true
        } else {
            false
        }
    }
    pub fn has_prev_sibling(&self) -> bool {
        // FIXME: Is this all...?
        self.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize - 1)
        }).unwrap_or(false)
    }
    pub fn go_to_prev_sibling(&mut self) -> bool {
        // pop history and string
        // decrease louds_pos and node_id by 1 if we have a sibling
        // get string (factor this out?)
        // push new history & string

        panic!("not implemented")
    }
    pub fn has_sibling(&self) -> bool {
        self.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize + 1)
        }).unwrap_or(false)
    }
    pub fn go_to_sibling(&mut self) -> bool {
        if let Some(h) = self.history_.pop() {
            if h.trie_.louds_.at(h.louds_pos_.0 as usize + 1) {
                // FIXME: What about LinkID?
                self.push(NodeID(h.node_id_.0 + 1),
                          LoudsPos(h.louds_pos_.0 + 1));
                true
            } else {
                false
            }
        } else {
            false
        }
    }
    pub fn has_parent(&self) -> bool {
        panic!("not implemented")
    }
    pub fn go_to_parent(&mut self) -> bool {
        // Could use LOUDS-trie select1(rank0(m)) to navigate upward (within a
        // single trie), but it's probably more efficient just to keep a stack
        // and pop to go up
        self.history_.pop().is_some()
    }
    pub fn is_leaf(&self) -> bool {
        panic!("not implemented")
    }
    //pub fn get_string(&self) -> &str {
    //    panic!("not implemented")
    //}
    pub fn get_u8(&self) -> &[u8] {
        &self.key_buf_[..]
    }
    pub fn is_end(&self) -> bool {
        panic!("not implemented")
    }
}

#[derive(Copy, Clone)]
enum DFT {
    ToChild,
    ToSibling,
    ToParentSibling,
    End
}

impl DFT {
    fn new() -> DFT {
        DFT::ToChild
    }
    fn depth_first_traversal_step<'a>(&mut self, nav: &mut Nav<'a>) -> bool {
        match *self {
            DFT::ToChild => {
                if nav.go_to_child() {
                    return true;
                } else {
                    *self = DFT::ToSibling;
                    return false;
                }
            },
            DFT::ToSibling => {
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                } else {
                    *self = DFT::ToParentSibling;
                    return false;
                }
            },
            DFT::ToParentSibling => {
                if !nav.go_to_parent() {
                    *self = DFT::End;
                    return false;
                }
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                }
                return false;
            },
            DFT::End => {
                return false;
            }
        }
    }
    fn next_terminal<'a, 'b>(&mut self, nav: &'b mut Nav<'a>)
      -> Option<&'b[u8]> {
        loop {
            match *self {
                DFT::End => { return None; },
                _ => (),
            }
            if self.depth_first_traversal_step(nav) {
                return Some(nav.get_u8());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use env_logger;
    use std::cmp::Ordering;
    use quickcheck as qc;
    use config::{Config, NumTries};
    use key::Key;
    use super::{DFT, Nav};
    use super::super::LoudsTrie;

    fn restore_with_nav_prop(v: Vec<String>, num_tries: NumTries)
      -> qc::TestResult {
        if v.iter().any(|x| x.is_empty()) {
            return qc::TestResult::discard();
        }
        let mut keys: Vec<Key> = v.iter().map(|s| Key::new(s.as_bytes()))
                                 .collect();
        let config = Config::new().with_num_tries(num_tries);
        let trie = LoudsTrie::build(&mut keys, &config);

        let mut nav = Nav::new(&trie);
        let mut dft = DFT::new();

        let mut vv1: Vec<Vec<u8>> = v.iter().map(|s| From::from(s.as_bytes()))
                                    .collect();

        let mut vv2: Vec<Vec<u8>> = Vec::new();
        while let Some(s) = dft.next_terminal(&mut nav) {
            vv2.push(From::from(s));
        }

        vv1.sort();
        vv2.sort();
        qc::TestResult::from_bool(vv1.cmp(&vv2) == Ordering::Equal)
        //qc::TestResult::passed()
    }

    #[test]
    fn restore_with_nav_qc() {
        let _ = env_logger::init();
        qc::quickcheck(restore_with_nav_prop as fn(Vec<String>, NumTries)
                       -> qc::TestResult);
    }

    #[test]
    fn restore_with_nav_manual() {
        panic!()

    }
}

<|endoftext|>


<commit_before>// Copyright 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.

//! Operations on ASCII strings and characters.

use to_str::{ToStr,ToStrConsume};
use str;
use str::StrSlice;
use cast;
use old_iter::BaseIter;
use iterator::IteratorUtil;
use vec::{CopyableVector, ImmutableVector, OwnedVector};
use to_bytes::IterBytes;

/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
#[deriving(Clone, Eq)]
pub struct Ascii { priv chr: u8 }

impl Ascii {
    /// Converts a ascii character into a `u8`.
    #[inline]
    pub fn to_byte(self) -> u8 {
        self.chr
    }

    /// Converts a ascii character into a `char`.
    #[inline]
    pub fn to_char(self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline]
    pub fn to_lower(self) -> Ascii {
        if self.chr >= 65 && self.chr <= 90 {
            Ascii{chr: self.chr | 0x20 }
        } else {
            self
        }
    }

    /// Convert to uppercase.
    #[inline]
    pub fn to_upper(self) -> Ascii {
        if self.chr >= 97 && self.chr <= 122 {
            Ascii{chr: self.chr & !0x20 }
        } else {
            self
        }
    }

    /// Compares two ascii characters of equality, ignoring case.
    #[inline]
    pub fn eq_ignore_case(self, other: Ascii) -> bool {
        self.to_lower().chr == other.to_lower().chr
    }
}

impl ToStr for Ascii {
    #[inline]
    fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) }
}

/// Trait for converting into an ascii type.
pub trait AsciiCast<T> {
    /// Convert to an ascii type
    fn to_ascii(&self) -> T;

    /// Convert to an ascii type, not doing any range asserts
    unsafe fn to_ascii_nocheck(&self) -> T;

    /// Check if convertible to ascii
    fn is_ascii(&self) -> bool;
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
    #[inline]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
        cast::transmute(*self)
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        for self.each |b| {
            if !b.is_ascii() { return false; }
        }
        true
    }
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
    #[inline]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
        let (p,len): (*u8, uint) = cast::transmute(*self);
        cast::transmute((p, len - 1))
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        self.bytes_iter().all(|b| b.is_ascii())
    }
}

impl AsciiCast<Ascii> for u8 {
    #[inline]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self }
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        *self & 128 == 0u8
    }
}

impl AsciiCast<Ascii> for char {
    #[inline]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self as u8 }
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        *self - ('\x7F' & *self) == '\x00'
    }
}

/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast {
    /// Take ownership and cast to an ascii vector without trailing zero element.
    fn into_ascii(self) -> ~[Ascii];

    /// Take ownership and cast to an ascii vector without trailing zero element.
    /// Does not perform validation checks.
    unsafe fn into_ascii_nocheck(self) -> ~[Ascii];
}

impl OwnedAsciiCast for ~[u8] {
    #[inline]
    fn into_ascii(self) -> ~[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.into_ascii_nocheck()}
    }

    #[inline]
    unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
        cast::transmute(self)
    }
}

impl OwnedAsciiCast for ~str {
    #[inline]
    fn into_ascii(self) -> ~[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.into_ascii_nocheck()}
    }

    #[inline]
    unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
        let mut r: ~[Ascii] = cast::transmute(self);
        r.pop();
        r
    }
}

/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
pub trait AsciiStr {
    /// Convert to a string.
    fn to_str_ascii(&self) -> ~str;

    /// Convert to vector representing a lower cased ascii string.
    fn to_lower(&self) -> ~[Ascii];

    /// Convert to vector representing a upper cased ascii string.
    fn to_upper(&self) -> ~[Ascii];

    /// Compares two Ascii strings ignoring case
    fn eq_ignore_case(self, other: &[Ascii]) -> bool;
}

impl<'self> AsciiStr for &'self [Ascii] {
    #[inline]
    fn to_str_ascii(&self) -> ~str {
        let mut cpy = self.to_owned();
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }

    #[inline]
    fn to_lower(&self) -> ~[Ascii] {
        self.map(|a| a.to_lower())
    }

    #[inline]
    fn to_upper(&self) -> ~[Ascii] {
        self.map(|a| a.to_upper())
    }

    #[inline]
    fn eq_ignore_case(self, other: &[Ascii]) -> bool {
        do self.iter().zip(other.iter()).all |(&a, &b)| { a.eq_ignore_case(b) }
    }
}

impl ToStrConsume for ~[Ascii] {
    #[inline]
    fn into_str(self) -> ~str {
        let mut cpy = self;
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }
}

impl IterBytes for Ascii {
    #[inline]
    fn iter_bytes(&self, _lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool {
        f([self.to_byte()])
    }
}

/// Trait to convert to a owned byte array by consuming self
pub trait ToBytesConsume {
    /// Converts to a owned byte array by consuming self
    fn into_bytes(self) -> ~[u8];
}

impl ToBytesConsume for ~[Ascii] {
    fn into_bytes(self) -> ~[u8] {
        unsafe {cast::transmute(self)}
    }
}

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

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
        (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
    )

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().to_byte(), 65u8);
        assert_eq!(65u8.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_byte(), 65u8);

        assert_eq!('A'.to_ascii().to_lower().to_char(), 'a');
        assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z');
        assert_eq!('a'.to_ascii().to_upper().to_char(), 'A');
        assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z');

        assert_eq!('@'.to_ascii().to_lower().to_char(), '@');
        assert_eq!('['.to_ascii().to_lower().to_char(), '[');
        assert_eq!('`'.to_ascii().to_upper().to_char(), '`');
        assert_eq!('{'.to_ascii().to_upper().to_char(), '{');

        assert!("banana".iter().all(|c| c.is_ascii()));
        assert!(!"ประเทศไทย中华Việt Nam".iter().all(|c| c.is_ascii()));
    }

    #[test]
    fn test_ascii_vec() {
        assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
        assert_eq!("( ;".to_ascii(),                 v2ascii!([40, 32, 59]));
        // FIXME: #5475 borrowchk error, owned vectors do not live long enough
        // if chained-from directly
        let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
        let v = ~"( ;";              assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));

        assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#");
        assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#");

        assert_eq!("".to_ascii().to_lower().to_str_ascii(), ~"");
        assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca");
        assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;");

        assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));

        assert!("".is_ascii());
        assert!("a".is_ascii());
        assert!(!"\u2009".is_ascii());

    }

    #[test]
    fn test_owned_ascii_vec() {
        assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59]));
        assert_eq!((~[40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59]));
    }

    #[test]
    fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }

    #[test]
    fn test_ascii_into_str() {
        assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;");
    }

    #[test]
    fn test_ascii_to_bytes() {
        assert_eq!(v2ascii!(~[40, 32, 59]).to_bytes(false), ~[40u8, 32u8, 59u8]);
        assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), ~[40u8, 32u8, 59u8]);
    }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_u8_slice()  { (&[127u8, 128u8, 255u8]).to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
}
<commit_msg>vec: remove BaseIter implementation<commit_after>// Copyright 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.

//! Operations on ASCII strings and characters.

use to_str::{ToStr,ToStrConsume};
use str;
use str::StrSlice;
use cast;
use iterator::IteratorUtil;
use vec::{CopyableVector, ImmutableVector, OwnedVector};
use to_bytes::IterBytes;

/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
#[deriving(Clone, Eq)]
pub struct Ascii { priv chr: u8 }

impl Ascii {
    /// Converts a ascii character into a `u8`.
    #[inline]
    pub fn to_byte(self) -> u8 {
        self.chr
    }

    /// Converts a ascii character into a `char`.
    #[inline]
    pub fn to_char(self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline]
    pub fn to_lower(self) -> Ascii {
        if self.chr >= 65 && self.chr <= 90 {
            Ascii{chr: self.chr | 0x20 }
        } else {
            self
        }
    }

    /// Convert to uppercase.
    #[inline]
    pub fn to_upper(self) -> Ascii {
        if self.chr >= 97 && self.chr <= 122 {
            Ascii{chr: self.chr & !0x20 }
        } else {
            self
        }
    }

    /// Compares two ascii characters of equality, ignoring case.
    #[inline]
    pub fn eq_ignore_case(self, other: Ascii) -> bool {
        self.to_lower().chr == other.to_lower().chr
    }
}

impl ToStr for Ascii {
    #[inline]
    fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) }
}

/// Trait for converting into an ascii type.
pub trait AsciiCast<T> {
    /// Convert to an ascii type
    fn to_ascii(&self) -> T;

    /// Convert to an ascii type, not doing any range asserts
    unsafe fn to_ascii_nocheck(&self) -> T;

    /// Check if convertible to ascii
    fn is_ascii(&self) -> bool;
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
    #[inline]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
        cast::transmute(*self)
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        for self.iter().advance |b| {
            if !b.is_ascii() { return false; }
        }
        true
    }
}

impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
    #[inline]
    fn to_ascii(&self) -> &'self[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'self[Ascii] {
        let (p,len): (*u8, uint) = cast::transmute(*self);
        cast::transmute((p, len - 1))
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        self.bytes_iter().all(|b| b.is_ascii())
    }
}

impl AsciiCast<Ascii> for u8 {
    #[inline]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self }
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        *self & 128 == 0u8
    }
}

impl AsciiCast<Ascii> for char {
    #[inline]
    fn to_ascii(&self) -> Ascii {
        assert!(self.is_ascii());
        unsafe {self.to_ascii_nocheck()}
    }

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self as u8 }
    }

    #[inline]
    fn is_ascii(&self) -> bool {
        *self - ('\x7F' & *self) == '\x00'
    }
}

/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast {
    /// Take ownership and cast to an ascii vector without trailing zero element.
    fn into_ascii(self) -> ~[Ascii];

    /// Take ownership and cast to an ascii vector without trailing zero element.
    /// Does not perform validation checks.
    unsafe fn into_ascii_nocheck(self) -> ~[Ascii];
}

impl OwnedAsciiCast for ~[u8] {
    #[inline]
    fn into_ascii(self) -> ~[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.into_ascii_nocheck()}
    }

    #[inline]
    unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
        cast::transmute(self)
    }
}

impl OwnedAsciiCast for ~str {
    #[inline]
    fn into_ascii(self) -> ~[Ascii] {
        assert!(self.is_ascii());
        unsafe {self.into_ascii_nocheck()}
    }

    #[inline]
    unsafe fn into_ascii_nocheck(self) -> ~[Ascii] {
        let mut r: ~[Ascii] = cast::transmute(self);
        r.pop();
        r
    }
}

/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
pub trait AsciiStr {
    /// Convert to a string.
    fn to_str_ascii(&self) -> ~str;

    /// Convert to vector representing a lower cased ascii string.
    fn to_lower(&self) -> ~[Ascii];

    /// Convert to vector representing a upper cased ascii string.
    fn to_upper(&self) -> ~[Ascii];

    /// Compares two Ascii strings ignoring case
    fn eq_ignore_case(self, other: &[Ascii]) -> bool;
}

impl<'self> AsciiStr for &'self [Ascii] {
    #[inline]
    fn to_str_ascii(&self) -> ~str {
        let mut cpy = self.to_owned();
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }

    #[inline]
    fn to_lower(&self) -> ~[Ascii] {
        self.map(|a| a.to_lower())
    }

    #[inline]
    fn to_upper(&self) -> ~[Ascii] {
        self.map(|a| a.to_upper())
    }

    #[inline]
    fn eq_ignore_case(self, other: &[Ascii]) -> bool {
        do self.iter().zip(other.iter()).all |(&a, &b)| { a.eq_ignore_case(b) }
    }
}

impl ToStrConsume for ~[Ascii] {
    #[inline]
    fn into_str(self) -> ~str {
        let mut cpy = self;
        cpy.push(0u8.to_ascii());
        unsafe {cast::transmute(cpy)}
    }
}

impl IterBytes for Ascii {
    #[inline]
    fn iter_bytes(&self, _lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool {
        f([self.to_byte()])
    }
}

/// Trait to convert to a owned byte array by consuming self
pub trait ToBytesConsume {
    /// Converts to a owned byte array by consuming self
    fn into_bytes(self) -> ~[u8];
}

impl ToBytesConsume for ~[Ascii] {
    fn into_bytes(self) -> ~[u8] {
        unsafe {cast::transmute(self)}
    }
}

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

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
        (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
    )

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().to_byte(), 65u8);
        assert_eq!(65u8.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_char(), 'A');
        assert_eq!('A'.to_ascii().to_byte(), 65u8);

        assert_eq!('A'.to_ascii().to_lower().to_char(), 'a');
        assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z');
        assert_eq!('a'.to_ascii().to_upper().to_char(), 'A');
        assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z');

        assert_eq!('@'.to_ascii().to_lower().to_char(), '@');
        assert_eq!('['.to_ascii().to_lower().to_char(), '[');
        assert_eq!('`'.to_ascii().to_upper().to_char(), '`');
        assert_eq!('{'.to_ascii().to_upper().to_char(), '{');

        assert!("banana".iter().all(|c| c.is_ascii()));
        assert!(!"ประเทศไทย中华Việt Nam".iter().all(|c| c.is_ascii()));
    }

    #[test]
    fn test_ascii_vec() {
        assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
        assert_eq!("( ;".to_ascii(),                 v2ascii!([40, 32, 59]));
        // FIXME: #5475 borrowchk error, owned vectors do not live long enough
        // if chained-from directly
        let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
        let v = ~"( ;";              assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));

        assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#");
        assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#");

        assert_eq!("".to_ascii().to_lower().to_str_ascii(), ~"");
        assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca");
        assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;");

        assert!("aBcDeF&?#".to_ascii().eq_ignore_case("AbCdEf&?#".to_ascii()));

        assert!("".is_ascii());
        assert!("a".is_ascii());
        assert!(!"\u2009".is_ascii());

    }

    #[test]
    fn test_owned_ascii_vec() {
        assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59]));
        assert_eq!((~[40u8, 32u8, 59u8]).into_ascii(), v2ascii!(~[40, 32, 59]));
    }

    #[test]
    fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }

    #[test]
    fn test_ascii_into_str() {
        assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;");
    }

    #[test]
    fn test_ascii_to_bytes() {
        assert_eq!(v2ascii!(~[40, 32, 59]).to_bytes(false), ~[40u8, 32u8, 59u8]);
        assert_eq!(v2ascii!(~[40, 32, 59]).into_bytes(), ~[40u8, 32u8, 59u8]);
    }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_u8_slice()  { (&[127u8, 128u8, 255u8]).to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }

    #[test] #[should_fail]
    fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
}
<|endoftext|>


<commit_before>extern crate rusqlite;

use super::{Wallet, WalletType};

use errors::wallet::WalletError;
use utils::environment::EnvironmentUtils;

use self::rusqlite::Connection;

use std::error::Error;
use std::fs;
use std::path::PathBuf;

pub struct DefaultWallet {
    name: String
}

impl DefaultWallet {
    fn new(name: &str) -> DefaultWallet {
        DefaultWallet {
            name: name.to_string()
        }
    }
}

impl Wallet for DefaultWallet {
    fn set(&self, key: &str, value: &str) -> Result<(), WalletError> {
        _open_connection(self.name.as_str())?
            .execute(
                "INSERT OR REPLACE INTO wallet (key, value) VALUES (?1, ?2)",
                &[&key.to_string(), &value.to_string()])?;
        Ok(())
    }

    fn get(&self, key: &str) -> Result<String, WalletError> {
        Ok(_open_connection(self.name.as_str())?
            .query_row(
                "SELECT value FROM wallet WHERE key = ?1 LIMIT 1",
                &[&key.to_string()],
                |row| row.get(0))?)
    }
}

pub struct DefaultWalletType {}

impl DefaultWalletType {
    pub fn new() -> DefaultWalletType {
        DefaultWalletType {}
    }
}

impl WalletType for DefaultWalletType {
    fn create(&self, name: &str, config: Option<&str>, credentials: Option<&str>) -> Result<(), WalletError> {
        let path = _db_path(name);
        if path.exists() {
            return Err(WalletError::AlreadyExists(name.to_string()))
        }

        _open_connection(name)?
            .execute("CREATE TABLE wallet (key TEXT CONSTRAINT constraint_name PRIMARY KEY, value TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)", &[])?;
        Ok(())
    }

    fn delete(&self, name: &str) -> Result<(), WalletError> {
        Ok(fs::remove_file(_db_path(name))?)
    }

    fn open(&self, name: &str, config: Option<&str>, credentials: Option<&str>) -> Result<Box<Wallet>, WalletError> {
        Ok(Box::new(DefaultWallet::new(name)))
    }
}

fn _db_path(name: &str) -> PathBuf {
    let mut path = EnvironmentUtils::wallet_path(name);
    path.push("sqlite.db");
    path
}

fn _open_connection(name: &str) -> Result<Connection, WalletError> {
    let path = _db_path(name);
    if !path.parent().unwrap().exists() {
        fs::DirBuilder::new()
            .recursive(true)
            .create(path.parent().unwrap())?;
    }

    Ok(Connection::open(path)?)
}

impl From<rusqlite::Error> for WalletError {
    fn from(err: rusqlite::Error) -> WalletError {
        match err {
            rusqlite::Error::QueryReturnedNoRows => WalletError::NotFound(err.description().to_string()),
            _ => WalletError::BackendError(err.description().to_string())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use errors::wallet::WalletError;
    use utils::test::TestUtils;

    #[test]
    fn type_new_works() {
        DefaultWalletType::new();
    }

    #[test]
    fn type_create_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn type_create_twice_fails() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        let res = wallet_type.create("wallet1", None, None);
        assert_match!(res, Err(WalletError::AlreadyExists(_)));

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn type_delete_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        wallet_type.delete("wallet1").unwrap();
        wallet_type.create("wallet1", None, None).unwrap();

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn type_open_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        wallet_type.open("wallet1", None, None).unwrap();

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_set_get_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        let wallet = wallet_type.open("wallet1", None, None).unwrap();

        wallet.set("key1", "value1").unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value1", value);

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_set_get_works_for_reopen() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        {
            let wallet = wallet_type.open("wallet1", None, None).unwrap();
            wallet.set("key1", "value1").unwrap();
        }

        let wallet = wallet_type.open("wallet1", None, None).unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value1", value);

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_get_works_for_unknown() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        let wallet = wallet_type.open("wallet1", None, None).unwrap();
        let value = wallet.get("key1");
        assert_match!(value,  Err(WalletError::NotFound(_)));

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_set_get_works_for_update() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        let wallet = wallet_type.open("wallet1", None, None).unwrap();

        wallet.set("key1", "value1").unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value1", value);

        wallet.set("key1", "value2").unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value2", value);

        TestUtils::cleanup_sovrin_home();
    }
}<commit_msg>* Debugging staff added<commit_after>extern crate rusqlite;

use super::{Wallet, WalletType};

use errors::wallet::WalletError;
use utils::environment::EnvironmentUtils;

use self::rusqlite::Connection;

use std::error::Error;
use std::fs;
use std::path::PathBuf;

pub struct DefaultWallet {
    name: String
}

impl DefaultWallet {
    fn new(name: &str) -> DefaultWallet {
        DefaultWallet {
            name: name.to_string()
        }
    }
}

impl Wallet for DefaultWallet {
    fn set(&self, key: &str, value: &str) -> Result<(), WalletError> {
        _open_connection(self.name.as_str())?
            .execute(
                "INSERT OR REPLACE INTO wallet (key, value) VALUES (?1, ?2)",
                &[&key.to_string(), &value.to_string()])?;
        Ok(())
    }

    fn get(&self, key: &str) -> Result<String, WalletError> {
        Ok(_open_connection(self.name.as_str())?
            .query_row(
                "SELECT value FROM wallet WHERE key = ?1 LIMIT 1",
                &[&key.to_string()],
                |row| row.get(0))?)
    }
}

pub struct DefaultWalletType {}

impl DefaultWalletType {
    pub fn new() -> DefaultWalletType {
        DefaultWalletType {}
    }
}

impl WalletType for DefaultWalletType {
    fn create(&self, name: &str, config: Option<&str>, credentials: Option<&str>) -> Result<(), WalletError> {
        let path = _db_path(name);
        if path.exists() {
            println!("---------3-> path exists {:?}", path);
            return Err(WalletError::AlreadyExists(name.to_string()))
        }

        _open_connection(name)?
            .execute("CREATE TABLE wallet (key TEXT CONSTRAINT constraint_name PRIMARY KEY, value TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)", &[])?;
        Ok(())
    }

    fn delete(&self, name: &str) -> Result<(), WalletError> {
        println!("---------2-> path {:?}", _db_path(name));
        println!("---------2-> path.exists() {:?}", _db_path(name).exists());
        Ok(fs::remove_file(_db_path(name))?)
    }

    fn open(&self, name: &str, config: Option<&str>, credentials: Option<&str>) -> Result<Box<Wallet>, WalletError> {
        Ok(Box::new(DefaultWallet::new(name)))
    }
}

fn _db_path(name: &str) -> PathBuf {
    let mut path = EnvironmentUtils::wallet_path(name);
    path.push("sqlite.db");
    path
}

fn _open_connection(name: &str) -> Result<Connection, WalletError> {
    let path = _db_path(name);
    if !path.parent().unwrap().exists() {
        println!("---------1-> path doesn't eists {:?}", path);
        fs::DirBuilder::new()
            .recursive(true)
            .create(path.parent().unwrap())?;
    }

    println!("---------1-> path {:?}", path);
    Ok(Connection::open(path)?)
}

impl From<rusqlite::Error> for WalletError {
    fn from(err: rusqlite::Error) -> WalletError {
        match err {
            rusqlite::Error::QueryReturnedNoRows => WalletError::NotFound(err.description().to_string()),
            _ => WalletError::BackendError(err.description().to_string())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use errors::wallet::WalletError;
    use utils::test::TestUtils;

    #[test]
    fn type_new_works() {
        DefaultWalletType::new();
    }

    #[test]
    fn type_create_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn type_create_twice_fails() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        let res = wallet_type.create("wallet1", None, None);
        assert_match!(res, Err(WalletError::AlreadyExists(_)));

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn type_delete_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        wallet_type.delete("wallet1").unwrap();
        wallet_type.create("wallet1", None, None).unwrap();

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn type_open_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        wallet_type.open("wallet1", None, None).unwrap();

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_set_get_works() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        let wallet = wallet_type.open("wallet1", None, None).unwrap();

        wallet.set("key1", "value1").unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value1", value);

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_set_get_works_for_reopen() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        {
            let wallet = wallet_type.open("wallet1", None, None).unwrap();
            wallet.set("key1", "value1").unwrap();
        }

        let wallet = wallet_type.open("wallet1", None, None).unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value1", value);

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_get_works_for_unknown() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();

        let wallet = wallet_type.open("wallet1", None, None).unwrap();
        let value = wallet.get("key1");
        assert_match!(value,  Err(WalletError::NotFound(_)));

        TestUtils::cleanup_sovrin_home();
    }

    #[test]
    fn wallet_set_get_works_for_update() {
        TestUtils::cleanup_sovrin_home();

        let wallet_type = DefaultWalletType::new();
        wallet_type.create("wallet1", None, None).unwrap();
        let wallet = wallet_type.open("wallet1", None, None).unwrap();

        wallet.set("key1", "value1").unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value1", value);

        wallet.set("key1", "value2").unwrap();
        let value = wallet.get("key1").unwrap();
        assert_eq!("value2", value);

        TestUtils::cleanup_sovrin_home();
    }
}<|endoftext|>