<commit_before>/// This function is where the kernel sets up IRQ handlers
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module

use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};

use acpi;
use allocator::{HEAP_START, HEAP_SIZE};
use externs::memset;
use gdt;
use idt;
use memory;
use paging::{self, entry, Page, VirtualAddress};

/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in BSS.
static BSS_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF;

static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT;

extern {
    /// Kernel main function
    fn kmain() -> !;
}

/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart() -> ! {
    {
        extern {
            /// The starting byte of the _.bss_ (uninitialized data) segment.
            static mut __bss_start: u8;
            /// The ending byte of the _.bss_ (uninitialized data) segment.
            static mut __bss_end: u8;
        }

        // Zero BSS, this initializes statics that are set to 0
        {
            let start_ptr = &mut __bss_start as *mut u8;
            let end_ptr = & __bss_end as *const u8 as usize;

            if start_ptr as usize <= end_ptr {
                let size = end_ptr - start_ptr as usize;
                memset(start_ptr, 0, size);
            }

            debug_assert_eq!(BSS_TEST_ZERO, 0);
            debug_assert_eq!(BSS_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF);
        }

        BSP_READY.store(false, Ordering::SeqCst);

        // Set up GDT
        gdt::init();

        // Set up IDT
        idt::init();

        // Initialize memory management
        memory::init(0, &__bss_end as *const u8 as usize);

        // TODO: allocate a stack
        let stack_start = 0x00080000;
        let stack_end = 0x0009F000;

        // Initialize paging
        let mut active_table = paging::init(stack_start, stack_end);

        // Read ACPI tables
        acpi::init(&mut active_table);

        // Map heap
        let heap_start_page = Page::containing_address(VirtualAddress::new(HEAP_START));
        let heap_end_page = Page::containing_address(VirtualAddress::new(HEAP_START + HEAP_SIZE-1));

        for page in Page::range_inclusive(heap_start_page, heap_end_page) {
            active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE);
        }

        BSP_READY.store(true, Ordering::SeqCst);
    }

    kmain();
}

/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(stack_start: usize, stack_end: usize) -> ! {
    {
        // Set up GDT for AP
        gdt::init_ap();

        // Set up IDT for aP
        idt::init_ap();

        // Initialize paging
        let mut active_table = paging::init(stack_start, stack_end);

        // Map heap
        let heap_start_page = Page::containing_address(VirtualAddress::new(HEAP_START));
        let heap_end_page = Page::containing_address(VirtualAddress::new(HEAP_START + HEAP_SIZE-1));

        for page in Page::range_inclusive(heap_start_page, heap_end_page) {
            active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE);
        }
    }

    while ! BSP_READY.load(Ordering::SeqCst) {
        asm!("pause" : : : : "intel", "volatile");
    }

    loop {
        asm!("hlt");
    }
}
<commit_msg>Do not map heap on AP, due to it being independent from the BSP heap. We need to adjust the mapping so that kernel mappings are shared accross processors, probably using higher half mapping for the kernel<commit_after>/// This function is where the kernel sets up IRQ handlers
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module

use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};

use acpi;
use allocator::{HEAP_START, HEAP_SIZE};
use externs::memset;
use gdt;
use idt;
use memory;
use paging::{self, entry, Page, VirtualAddress};

/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in BSS.
static BSS_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF;

static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT;

extern {
    /// Kernel main function
    fn kmain() -> !;
}

/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart() -> ! {
    {
        extern {
            /// The starting byte of the _.bss_ (uninitialized data) segment.
            static mut __bss_start: u8;
            /// The ending byte of the _.bss_ (uninitialized data) segment.
            static mut __bss_end: u8;
        }

        // Zero BSS, this initializes statics that are set to 0
        {
            let start_ptr = &mut __bss_start as *mut u8;
            let end_ptr = & __bss_end as *const u8 as usize;

            if start_ptr as usize <= end_ptr {
                let size = end_ptr - start_ptr as usize;
                memset(start_ptr, 0, size);
            }

            debug_assert_eq!(BSS_TEST_ZERO, 0);
            debug_assert_eq!(BSS_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF);
        }

        BSP_READY.store(false, Ordering::SeqCst);

        // Set up GDT
        gdt::init();

        // Set up IDT
        idt::init();

        // Initialize memory management
        memory::init(0, &__bss_end as *const u8 as usize);

        // TODO: allocate a stack
        let stack_start = 0x00080000;
        let stack_end = 0x0009F000;

        // Initialize paging
        let mut active_table = paging::init(stack_start, stack_end);

        // Read ACPI tables
        acpi::init(&mut active_table);

        // Map heap
        let heap_start_page = Page::containing_address(VirtualAddress::new(HEAP_START));
        let heap_end_page = Page::containing_address(VirtualAddress::new(HEAP_START + HEAP_SIZE-1));

        for page in Page::range_inclusive(heap_start_page, heap_end_page) {
            active_table.map(page, entry::WRITABLE | entry::NO_EXECUTE);
        }

        BSP_READY.store(true, Ordering::SeqCst);
    }

    kmain();
}

/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(stack_start: usize, stack_end: usize) -> ! {
    {
        // Set up GDT for AP
        gdt::init_ap();

        // Set up IDT for aP
        idt::init_ap();

        // Initialize paging
        //let mut active_table =
        paging::init(stack_start, stack_end);

        // TODO: Use heap from master, ensuring consistency
    }

    while ! BSP_READY.load(Ordering::SeqCst) {
        asm!("pause" : : : : "intel", "volatile");
    }

    loop {
        asm!("hlt");
    }
}
<|endoftext|>


<commit_before>/*!
`ed25519`, a signature scheme specified in
[Ed25519](http://ed25519.cr.yp.to/). This function is conjectured to meet the
standard notion of unforgeability for a public-key signature scheme under
chosen-message attacks.
*/
#[cfg(test)]
extern crate serialize;
use ffi;
use libc::c_ulonglong;
use std::intrinsics::volatile_set_memory;
use std::iter::repeat;

pub const SEEDBYTES: usize = ffi::crypto_sign_ed25519_SEEDBYTES as usize;
pub const SECRETKEYBYTES: usize = ffi::crypto_sign_ed25519_SECRETKEYBYTES as usize;
pub const PUBLICKEYBYTES: usize = ffi::crypto_sign_ed25519_PUBLICKEYBYTES as usize;
pub const SIGNATUREBYTES: usize = ffi::crypto_sign_ed25519_BYTES as usize;

/**
 * `Seed` that can be used for keypair generation
 *
 * The `Seed` is used by `keypair_from_seed()` to generate
 * a secret and public signature key.
 *
 * When a `Seed` goes out of scope its contents
 * will be zeroed out
 */
pub struct Seed(pub [u8; SEEDBYTES]);

newtype_drop!(Seed);
newtype_clone!(Seed);
newtype_impl!(Seed, SEEDBYTES);

/**
 * `SecretKey` for signatures
 *
 * When a `SecretKey` goes out of scope its contents
 * will be zeroed out
 */
pub struct SecretKey(pub [u8; SECRETKEYBYTES]);

newtype_drop!(SecretKey);
newtype_clone!(SecretKey);
newtype_impl!(SecretKey, SECRETKEYBYTES);

/**
 * `PublicKey` for signatures
 */
#[derive(Copy)]
pub struct PublicKey(pub [u8; PUBLICKEYBYTES]);

newtype_clone!(PublicKey);
newtype_impl!(PublicKey, PUBLICKEYBYTES);

/**
 * Detached signature
 */
#[derive(Copy)]
pub struct Signature(pub [u8; SIGNATUREBYTES]);

newtype_clone!(Signature);
newtype_impl!(Signature, SIGNATUREBYTES);

/**
 * `gen_keypair()` randomly generates a secret key and a corresponding public
 * key.
 *
 * THREAD SAFETY: `gen_keypair()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_keypair() -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8; PUBLICKEYBYTES];
        let mut sk = [0u8; SECRETKEYBYTES];
        ffi::crypto_sign_ed25519_keypair(pk.as_mut_ptr(), sk.as_mut_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `keypair_from_seed()` computes a secret key and a corresponding public key
 * from a `Seed`.
 */
pub fn keypair_from_seed(&Seed(seed): &Seed) -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8; PUBLICKEYBYTES];
        let mut sk = [0u8; SECRETKEYBYTES];
        ffi::crypto_sign_ed25519_seed_keypair(pk.as_mut_ptr(),
                                         sk.as_mut_ptr(),
                                         seed.as_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `sign()` signs a message `m` using the signer's secret key `sk`.
 * `sign()` returns the resulting signed message `sm`.
 */
pub fn sign(m: &[u8],
            &SecretKey(sk): &SecretKey) -> Vec<u8> {
    unsafe {
        let mut sm: Vec<u8> = repeat(0u8).take(m.len() + SIGNATUREBYTES).collect();
        let mut smlen = 0;
        ffi::crypto_sign_ed25519(sm.as_mut_ptr(),
                                 &mut smlen,
                                 m.as_ptr(),
                                 m.len() as c_ulonglong,
                                 sk.as_ptr());
        sm.truncate(smlen as usize);
        sm
    }
}

/**
 * `verify()` verifies the signature in `sm` using the signer's public key `pk`.
 * `verify()` returns the message `Some(m)`.
 * If the signature fails verification, `verify()` returns `None`.
 */
pub fn verify(sm: &[u8],
              &PublicKey(pk): &PublicKey) -> Option<Vec<u8>> {
    unsafe {
        let mut m: Vec<u8> = repeat(0u8).take(sm.len()).collect();
        let mut mlen = 0;
        if ffi::crypto_sign_ed25519_open(m.as_mut_ptr(),
                                         &mut mlen,
                                         sm.as_ptr(),
                                         sm.len() as c_ulonglong,
                                         pk.as_ptr()) == 0 {
            m.truncate(mlen as usize);
            Some(m)
        } else {
            None
        }
    }
}

/**
 * `sign_detached()` signs a message `m` using the signer's secret key `sk`.
 * `sign_detached()` returns the resulting signature `sig`.
 */
pub fn sign_detached(m: &[u8],
                     &SecretKey(sk): &SecretKey) -> Signature {
    unsafe {
        let mut sig = [0u8; SIGNATUREBYTES];
        let mut siglen: c_ulonglong = 0;
        ffi::crypto_sign_ed25519_detached(sig.as_mut_ptr(),
                                          &mut siglen,
                                          m.as_ptr(),
                                          m.len() as c_ulonglong,
                                          sk.as_ptr());
        assert_eq!(siglen, SIGNATUREBYTES as c_ulonglong);
        Signature(sig)
    }
}

/**
 * `verify_detached()` verifies the signature in `sig` against the message `m`
 * and the signer's public key `pk`.
 * `verify_detached()` returns true if the signature is valid, false otherwise.
 */
pub fn verify_detached(&Signature(sig): &Signature,
                       m: &[u8],
                       &PublicKey(pk): &PublicKey) -> bool {
    unsafe {
        0 == ffi::crypto_sign_ed25519_verify_detached(sig.as_ptr(),
                                                      m.as_ptr(),
                                                      m.len() as c_ulonglong,
                                                      pk.as_ptr())
    }
}

#[test]
fn test_sign_verify() {
    use randombytes::randombytes;
    for i in (0..256us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let sm = sign(m.as_slice(), &sk);
        let m2 = verify(sm.as_slice(), &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper() {
    use randombytes::randombytes;
    for i in (0..32us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let mut smv = sign(m.as_slice(), &sk);
        let sm = smv.as_mut_slice();
        for j in (0..sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_sign_verify_detached() {
    use randombytes::randombytes;
    for i in (0..256us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let sig = sign_detached(m.as_slice(), &sk);
        assert!(verify_detached(&sig, m.as_slice(), &pk));
    }
}

#[test]
fn test_sign_verify_detached_tamper() {
    use randombytes::randombytes;
    for i in (0..32us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let Signature(mut sig) = sign_detached(m.as_slice(), &sk);
        for j in (0..SIGNATUREBYTES) {
            sig[j] ^= 0x20;
            assert!(!verify_detached(&Signature(sig), m.as_slice(), &pk));
            sig[j] ^= 0x20;
        }
    }
}

#[test]
fn test_sign_verify_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in (0..256us) {
        let mut seedbuf = [0; 32];
        randombytes_into(&mut seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i);
        let sm = sign(m.as_slice(), &sk);
        let m2 = verify(sm.as_slice(), &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in (0..32us) {
        let mut seedbuf = [0; 32];
        randombytes_into(&mut seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i);
        let mut smv = sign(m.as_slice(), &sk);
        let sm = smv.as_mut_slice();
        for j in (0..sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_vectors() {
    // test vectors from the Python implementation
    // from the [Ed25519 Homepage](http://ed25519.cr.yp.to/software.html)
    use self::serialize::hex::{FromHex, ToHex};
    use std::io::BufferedReader;
    use std::io::File;
    use std::path::Path;

    let p = &Path::new("testvectors/ed25519.input");
    let mut r = BufferedReader::new(File::open(p).unwrap());
    loop {
        let line = match r.read_line() {
            Err(_) => break,
            Ok(line) => line
        };
        let mut x = line.as_slice().split(':');
        let x0 = x.next().unwrap();
        let x1 = x.next().unwrap();
        let x2 = x.next().unwrap();
        let x3 = x.next().unwrap();
        let seed_bytes = x0.slice(0, 64).from_hex().unwrap();
        assert!(seed_bytes.len() == SEEDBYTES);
        let mut seedbuf = [0u8; SEEDBYTES];
        for (s, b) in seedbuf.iter_mut().zip(seed_bytes.iter()) {
            *s = *b
        }
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = x2.from_hex().unwrap();
        let sm = sign(m.as_slice(), &sk);
        verify(sm.as_slice(), &pk).unwrap();
        let PublicKey(pkbuf) = pk;
        assert!(x1 == pkbuf.as_slice().to_hex().as_slice());
        assert!(x3 == sm.as_slice().to_hex().as_slice());
    }
}

#[test]
fn test_vectors_detached() {
    // test vectors from the Python implementation
    // from the [Ed25519 Homepage](http://ed25519.cr.yp.to/software.html)
    use self::serialize::hex::{FromHex, ToHex};
    use std::io::BufferedReader;
    use std::io::File;
    use std::path::Path;

    let p = &Path::new("testvectors/ed25519.input");
    let mut r = BufferedReader::new(File::open(p).unwrap());
    loop {
        let line = match r.read_line() {
            Err(_) => break,
            Ok(line) => line
        };
        let mut x = line.as_slice().split(':');
        let x0 = x.next().unwrap();
        let x1 = x.next().unwrap();
        let x2 = x.next().unwrap();
        let x3 = x.next().unwrap();
        let seed_bytes = x0.slice(0, 64).from_hex().unwrap();
        assert!(seed_bytes.len() == SEEDBYTES);
        let mut seedbuf = [0u8; SEEDBYTES];
        for (s, b) in seedbuf.iter_mut().zip(seed_bytes.iter()) {
            *s = *b
        }
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = x2.from_hex().unwrap();
        let sig = sign_detached(m.as_slice(), &sk);
        assert!(verify_detached(&sig, m.as_slice(), &pk));
        let PublicKey(pkbuf) = pk;
        assert!(x1 == pkbuf.as_slice().to_hex().as_slice());
        let sm = sig.as_slice().to_hex() + x2; // x2 is m hex encoded
        assert!(x3 == sm);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use randombytes::randombytes;
    use super::*;

    const BENCH_SIZES: [usize; 14] = [0, 1, 2, 4, 8, 16, 32, 64,
                                      128, 256, 512, 1024, 2048, 4096];

    #[bench]
    fn bench_sign(b: &mut test::Bencher) {
        let (_, sk) = gen_keypair();
        let ms: Vec<Vec<u8>> = BENCH_SIZES.iter().map(|s| {
            randombytes(*s)
        }).collect();
        b.iter(|| {
            for m in ms.iter() {
                sign(m.as_slice(), &sk);
            }
        });
    }

    #[bench]
    fn bench_verify(b: &mut test::Bencher) {
        let (pk, sk) = gen_keypair();
        let sms: Vec<Vec<u8>> = BENCH_SIZES.iter().map(|s| {
            let m = randombytes(*s);
            sign(m.as_slice(), &sk)
        }).collect();
        b.iter(|| {
            for sm in sms.iter() {
                verify(sm.as_slice(), &pk);
            }
        });
    }
}
<commit_msg>Cleanup of tests<commit_after>/*!
`ed25519`, a signature scheme specified in
[Ed25519](http://ed25519.cr.yp.to/). This function is conjectured to meet the
standard notion of unforgeability for a public-key signature scheme under
chosen-message attacks.
*/
#[cfg(test)]
extern crate serialize;
use ffi;
use libc::c_ulonglong;
use std::intrinsics::volatile_set_memory;
use std::iter::repeat;

pub const SEEDBYTES: usize = ffi::crypto_sign_ed25519_SEEDBYTES as usize;
pub const SECRETKEYBYTES: usize = ffi::crypto_sign_ed25519_SECRETKEYBYTES as usize;
pub const PUBLICKEYBYTES: usize = ffi::crypto_sign_ed25519_PUBLICKEYBYTES as usize;
pub const SIGNATUREBYTES: usize = ffi::crypto_sign_ed25519_BYTES as usize;

/**
 * `Seed` that can be used for keypair generation
 *
 * The `Seed` is used by `keypair_from_seed()` to generate
 * a secret and public signature key.
 *
 * When a `Seed` goes out of scope its contents
 * will be zeroed out
 */
pub struct Seed(pub [u8; SEEDBYTES]);

newtype_drop!(Seed);
newtype_clone!(Seed);
newtype_impl!(Seed, SEEDBYTES);

/**
 * `SecretKey` for signatures
 *
 * When a `SecretKey` goes out of scope its contents
 * will be zeroed out
 */
pub struct SecretKey(pub [u8; SECRETKEYBYTES]);

newtype_drop!(SecretKey);
newtype_clone!(SecretKey);
newtype_impl!(SecretKey, SECRETKEYBYTES);

/**
 * `PublicKey` for signatures
 */
#[derive(Copy)]
pub struct PublicKey(pub [u8; PUBLICKEYBYTES]);

newtype_clone!(PublicKey);
newtype_impl!(PublicKey, PUBLICKEYBYTES);

/**
 * Detached signature
 */
#[derive(Copy)]
pub struct Signature(pub [u8; SIGNATUREBYTES]);

newtype_clone!(Signature);
newtype_impl!(Signature, SIGNATUREBYTES);

/**
 * `gen_keypair()` randomly generates a secret key and a corresponding public
 * key.
 *
 * THREAD SAFETY: `gen_keypair()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_keypair() -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8; PUBLICKEYBYTES];
        let mut sk = [0u8; SECRETKEYBYTES];
        ffi::crypto_sign_ed25519_keypair(pk.as_mut_ptr(), sk.as_mut_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `keypair_from_seed()` computes a secret key and a corresponding public key
 * from a `Seed`.
 */
pub fn keypair_from_seed(&Seed(seed): &Seed) -> (PublicKey, SecretKey) {
    unsafe {
        let mut pk = [0u8; PUBLICKEYBYTES];
        let mut sk = [0u8; SECRETKEYBYTES];
        ffi::crypto_sign_ed25519_seed_keypair(pk.as_mut_ptr(),
                                         sk.as_mut_ptr(),
                                         seed.as_ptr());
        (PublicKey(pk), SecretKey(sk))
    }
}

/**
 * `sign()` signs a message `m` using the signer's secret key `sk`.
 * `sign()` returns the resulting signed message `sm`.
 */
pub fn sign(m: &[u8],
            &SecretKey(sk): &SecretKey) -> Vec<u8> {
    unsafe {
        let mut sm: Vec<u8> = repeat(0u8).take(m.len() + SIGNATUREBYTES).collect();
        let mut smlen = 0;
        ffi::crypto_sign_ed25519(sm.as_mut_ptr(),
                                 &mut smlen,
                                 m.as_ptr(),
                                 m.len() as c_ulonglong,
                                 sk.as_ptr());
        sm.truncate(smlen as usize);
        sm
    }
}

/**
 * `verify()` verifies the signature in `sm` using the signer's public key `pk`.
 * `verify()` returns the message `Some(m)`.
 * If the signature fails verification, `verify()` returns `None`.
 */
pub fn verify(sm: &[u8],
              &PublicKey(pk): &PublicKey) -> Option<Vec<u8>> {
    unsafe {
        let mut m: Vec<u8> = repeat(0u8).take(sm.len()).collect();
        let mut mlen = 0;
        if ffi::crypto_sign_ed25519_open(m.as_mut_ptr(),
                                         &mut mlen,
                                         sm.as_ptr(),
                                         sm.len() as c_ulonglong,
                                         pk.as_ptr()) == 0 {
            m.truncate(mlen as usize);
            Some(m)
        } else {
            None
        }
    }
}

/**
 * `sign_detached()` signs a message `m` using the signer's secret key `sk`.
 * `sign_detached()` returns the resulting signature `sig`.
 */
pub fn sign_detached(m: &[u8],
                     &SecretKey(sk): &SecretKey) -> Signature {
    unsafe {
        let mut sig = [0u8; SIGNATUREBYTES];
        let mut siglen: c_ulonglong = 0;
        ffi::crypto_sign_ed25519_detached(sig.as_mut_ptr(),
                                          &mut siglen,
                                          m.as_ptr(),
                                          m.len() as c_ulonglong,
                                          sk.as_ptr());
        assert_eq!(siglen, SIGNATUREBYTES as c_ulonglong);
        Signature(sig)
    }
}

/**
 * `verify_detached()` verifies the signature in `sig` against the message `m`
 * and the signer's public key `pk`.
 * `verify_detached()` returns true if the signature is valid, false otherwise.
 */
pub fn verify_detached(&Signature(sig): &Signature,
                       m: &[u8],
                       &PublicKey(pk): &PublicKey) -> bool {
    unsafe {
        0 == ffi::crypto_sign_ed25519_verify_detached(sig.as_ptr(),
                                                      m.as_ptr(),
                                                      m.len() as c_ulonglong,
                                                      pk.as_ptr())
    }
}

#[test]
fn test_sign_verify() {
    use randombytes::randombytes;
    for i in (0..256us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let sm = sign(m.as_slice(), &sk);
        let m2 = verify(sm.as_slice(), &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper() {
    use randombytes::randombytes;
    for i in (0..32us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let mut smv = sign(m.as_slice(), &sk);
        let sm = smv.as_mut_slice();
        for j in (0..sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_sign_verify_detached() {
    use randombytes::randombytes;
    for i in (0..256us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let sig = sign_detached(m.as_slice(), &sk);
        assert!(verify_detached(&sig, m.as_slice(), &pk));
    }
}

#[test]
fn test_sign_verify_detached_tamper() {
    use randombytes::randombytes;
    for i in (0..32us) {
        let (pk, sk) = gen_keypair();
        let m = randombytes(i);
        let Signature(mut sig) = sign_detached(m.as_slice(), &sk);
        for j in (0..SIGNATUREBYTES) {
            sig[j] ^= 0x20;
            assert!(!verify_detached(&Signature(sig), m.as_slice(), &pk));
            sig[j] ^= 0x20;
        }
    }
}

#[test]
fn test_sign_verify_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in (0..256us) {
        let mut seedbuf = [0; 32];
        randombytes_into(&mut seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i);
        let sm = sign(m.as_slice(), &sk);
        let m2 = verify(sm.as_slice(), &pk);
        assert!(Some(m) == m2);
    }
}

#[test]
fn test_sign_verify_tamper_seed() {
    use randombytes::{randombytes, randombytes_into};
    for i in (0..32us) {
        let mut seedbuf = [0; 32];
        randombytes_into(&mut seedbuf);
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = randombytes(i);
        let mut smv = sign(m.as_slice(), &sk);
        let sm = smv.as_mut_slice();
        for j in (0..sm.len()) {
            sm[j] ^= 0x20;
            assert!(None == verify(sm, &pk));
            sm[j] ^= 0x20;
        }
    }
}

#[test]
fn test_vectors() {
    // test vectors from the Python implementation
    // from the [Ed25519 Homepage](http://ed25519.cr.yp.to/software.html)
    use self::serialize::hex::{FromHex, ToHex};
    use std::io::BufferedReader;
    use std::io::File;
    use std::path::Path;

    let p = &Path::new("testvectors/ed25519.input");
    let mut r = BufferedReader::new(File::open(p).unwrap());
    loop {
        let line = match r.read_line() {
            Err(_) => break,
            Ok(line) => line
        };
        let mut x = line.as_slice().split(':');
        let x0 = x.next().unwrap();
        let x1 = x.next().unwrap();
        let x2 = x.next().unwrap();
        let x3 = x.next().unwrap();
        let seed_bytes = x0.slice(0, 64).from_hex().unwrap();
        assert!(seed_bytes.len() == SEEDBYTES);
        let mut seedbuf = [0u8; SEEDBYTES];
        for (s, b) in seedbuf.iter_mut().zip(seed_bytes.iter()) {
            *s = *b
        }
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = x2.from_hex().unwrap();
        let sm = sign(m.as_slice(), &sk);
        verify(sm.as_slice(), &pk).unwrap();
        assert!(x1 == pk.as_slice().to_hex().as_slice());
        assert!(x3 == sm.as_slice().to_hex().as_slice());
    }
}

#[test]
fn test_vectors_detached() {
    // test vectors from the Python implementation
    // from the [Ed25519 Homepage](http://ed25519.cr.yp.to/software.html)
    use self::serialize::hex::{FromHex, ToHex};
    use std::io::BufferedReader;
    use std::io::File;
    use std::path::Path;

    let p = &Path::new("testvectors/ed25519.input");
    let mut r = BufferedReader::new(File::open(p).unwrap());
    loop {
        let line = match r.read_line() {
            Err(_) => break,
            Ok(line) => line
        };
        let mut x = line.as_slice().split(':');
        let x0 = x.next().unwrap();
        let x1 = x.next().unwrap();
        let x2 = x.next().unwrap();
        let x3 = x.next().unwrap();
        let seed_bytes = x0.slice(0, 64).from_hex().unwrap();
        assert!(seed_bytes.len() == SEEDBYTES);
        let mut seedbuf = [0u8; SEEDBYTES];
        for (s, b) in seedbuf.iter_mut().zip(seed_bytes.iter()) {
            *s = *b
        }
        let seed = Seed(seedbuf);
        let (pk, sk) = keypair_from_seed(&seed);
        let m = x2.from_hex().unwrap();
        let sig = sign_detached(m.as_slice(), &sk);
        assert!(verify_detached(&sig, m.as_slice(), &pk));
        assert!(x1 == pk.as_slice().to_hex().as_slice());
        let sm = sig.as_slice().to_hex() + x2; // x2 is m hex encoded
        assert!(x3 == sm);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use randombytes::randombytes;
    use super::*;

    const BENCH_SIZES: [usize; 14] = [0, 1, 2, 4, 8, 16, 32, 64,
                                      128, 256, 512, 1024, 2048, 4096];

    #[bench]
    fn bench_sign(b: &mut test::Bencher) {
        let (_, sk) = gen_keypair();
        let ms: Vec<Vec<u8>> = BENCH_SIZES.iter().map(|s| {
            randombytes(*s)
        }).collect();
        b.iter(|| {
            for m in ms.iter() {
                sign(m.as_slice(), &sk);
            }
        });
    }

    #[bench]
    fn bench_verify(b: &mut test::Bencher) {
        let (pk, sk) = gen_keypair();
        let sms: Vec<Vec<u8>> = BENCH_SIZES.iter().map(|s| {
            let m = randombytes(*s);
            sign(m.as_slice(), &sk)
        }).collect();
        b.iter(|| {
            for sm in sms.iter() {
                verify(sm.as_slice(), &pk);
            }
        });
    }
}
<|endoftext|>


<commit_before>use ffi::*;
use std::mem;
use std::ptr;
use std::ffi::CString;

pub struct Caps{
	caps: *mut GstCaps
}

impl Drop for Caps{
	fn drop(&mut self){
        unsafe{
			gst_mini_object_unref(self.caps as *mut GstMiniObject);
		}
	}
}

impl Caps{
	pub unsafe fn new(caps: *mut GstCaps, owned: bool) -> Option<Caps>{
	    if caps != ptr::null_mut(){
			if !owned {gst_mini_object_ref(caps as *mut GstMiniObject);}
			Some(Caps{caps: caps})
		}else{
		    None
		}
	}

	pub fn from_string(desc: &str) -> Option<Caps>{
		let cdesc = CString::new(desc).unwrap();
	    unsafe{
	    	Caps::new(gst_caps_from_string(mem::transmute(desc.as_ptr())),true)
	    }
	}

	pub fn video_info(&self) -> Option<::VideoInfo>{
		unsafe{
			let videoinfo = ::VideoInfo::new();
			if gst_video_info_from_caps (mem::transmute(&videoinfo), mem::transmute(self.caps)) == 1 {
				Some(videoinfo)
			}else{
			    None
			}
		}
	}

	pub unsafe fn gst_caps(&self) -> *const GstCaps{
		self.caps
	}

	pub unsafe fn gst_caps_mut(&mut self) -> *mut GstCaps{
		self.caps
	}
}

impl ::Transfer<GstCaps> for Caps{
    unsafe fn transfer(self) ->  *mut GstCaps{
        let caps = self.caps;
		mem::forget(self);
        caps
    }
}
<commit_msg>caps: fix string being passed directly from rust version to c<commit_after>use ffi::*;
use std::mem;
use std::ptr;
use std::ffi::CString;

pub struct Caps{
	caps: *mut GstCaps
}

impl Drop for Caps{
	fn drop(&mut self){
        unsafe{
			gst_mini_object_unref(self.caps as *mut GstMiniObject);
		}
	}
}

impl Caps{
	pub unsafe fn new(caps: *mut GstCaps, owned: bool) -> Option<Caps>{
	    if caps != ptr::null_mut(){
			if !owned {gst_mini_object_ref(caps as *mut GstMiniObject);}
			Some(Caps{caps: caps})
		}else{
		    None
		}
	}

	pub fn from_string(desc: &str) -> Option<Caps>{
		let cdesc = CString::new(desc).unwrap();
	    unsafe{
	    	Caps::new(gst_caps_from_string(mem::transmute(cdesc.as_ptr())),true)
	    }
	}

	pub fn video_info(&self) -> Option<::VideoInfo>{
		unsafe{
			let videoinfo = ::VideoInfo::new();
			if gst_video_info_from_caps (mem::transmute(&videoinfo), mem::transmute(self.caps)) == 1 {
				Some(videoinfo)
			}else{
			    None
			}
		}
	}

	pub unsafe fn gst_caps(&self) -> *const GstCaps{
		self.caps
	}

	pub unsafe fn gst_caps_mut(&mut self) -> *mut GstCaps{
		self.caps
	}
}

impl ::Transfer<GstCaps> for Caps{
    unsafe fn transfer(self) ->  *mut GstCaps{
        let caps = self.caps;
		mem::forget(self);
        caps
    }
}
<|endoftext|>


<commit_before><commit_msg>Added default to decimal<commit_after><|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GdkDeviceManager — Functions for handling input devices

use glib::translate::*;
use glib::types::{StaticType, Type};
use device::Device;
use display::Display;
use object::Object;
use ffi;

pub type DeviceManager = Object<ffi::GdkDeviceManager>;

impl StaticType for DeviceManager {
    fn static_type() -> Type { unsafe { from_glib(ffi::gdk_device_manager_get_type()) } }
}

impl DeviceManager {
    pub fn disable_multidevice() {
        unsafe { ffi::gdk_disable_multidevice() }
    }

    pub fn get_display(&self) -> Option<Display> {
        unsafe { from_glib_none(ffi::gdk_device_manager_get_display(self.to_glib_none().0)) }
    }

    pub fn get_client_pointer(&self) -> Device {
        unsafe {
            from_glib_none(
                ffi::gdk_device_manager_get_client_pointer(self.to_glib_none().0))
        }
    }
}
<commit_msg>Add DeviceManager documentation<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GdkDeviceManager — Functions for handling input devices
//!
//! #Description
//!
//! In addition to a single pointer and keyboard for user interface input, GDK contains support
//! for a variety of input devices, including graphics tablets, touchscreens and multiple
//! pointers/keyboards interacting simultaneously with the user interface. Such input devices
//! often have additional features, such as sub-pixel positioning information and additional
//! device-dependent information.
//!
//! In order to query the device hierarchy and be aware of changes in the device hierarchy
//! (such as virtual devices being created or removed, or physical devices being plugged or
//! unplugged), GDK provides DeviceManager.
//!
//! By default, and if the platform supports it, GDK is aware of multiple keyboard/pointer pairs
//! and multitouch devices. This behavior can be changed by calling
//! DeviceManager::disable_multidevice() before Display::open(). There should rarely be a need to
//! do that though, since GDK defaults to a compatibility mode in which it will emit just one
//! enter/leave event pair for all devices on a window. To enable per-device enter/leave events
//! and other multi-pointer interaction features, Window::set_support_multidevice() must be called
//! on gdk::Windows (or gtk::Widget::set_support_multidevice() on widgets) window. See the
//! Window::set_support_multidevice() documentation for more information.
//!
//! On X11, multi-device support is implemented through XInput 2. Unless
//! DeviceManager::disable_multidevice() is called, the XInput 2 GdkDeviceManager implementation
//! will be used as the input source. Otherwise either the core or XInput 1 implementations will
//! be used.
//!
//! For simple applications that don’t have any special interest in input devices, the so-called
//! “client pointer” provides a reasonable approximation to a simple setup with a single pointer
//! and keyboard. The device that has been set as the client pointer can be accessed via
//! DeviceManager::get_client_pointer().
//!
//! Conceptually, in multidevice mode there are 2 device types. Virtual devices (or master devices)
//! are represented by the pointer cursors and keyboard foci that are seen on the screen. Physical
//! devices (or slave devices) represent the hardware that is controlling the virtual devices, and
//! thus have no visible cursor on the screen.
//!
//! Virtual devices are always paired, so there is a keyboard device for every pointer device.
//! Associations between devices may be inspected through Device::get_associated_device().
//!
//! There may be several virtual devices, and several physical devices could be controlling each of
//! these virtual devices. Physical devices may also be “floating”, which means they are not attached
//! to any virtual device.
//!
//! #Master and slave devices
//!
//! ``ìgnore
//! carlos@sacarino:~$ xinput list
//! ⎡ Virtual core pointer                          id=2    [master pointer  (3)]
//! ⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
//! ⎜   ↳ Wacom ISDv4 E6 Pen stylus                 id=10   [slave  pointer  (2)]
//! ⎜   ↳ Wacom ISDv4 E6 Finger touch               id=11   [slave  pointer  (2)]
//! ⎜   ↳ SynPS/2 Synaptics TouchPad                id=13   [slave  pointer  (2)]
//! ⎜   ↳ TPPS/2 IBM TrackPoint                     id=14   [slave  pointer  (2)]
//! ⎜   ↳ Wacom ISDv4 E6 Pen eraser                 id=16   [slave  pointer  (2)]
//! ⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
//!     ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
//!     ↳ Power Button                              id=6    [slave  keyboard (3)]
//!     ↳ Video Bus                                 id=7    [slave  keyboard (3)]
//!     ↳ Sleep Button                              id=8    [slave  keyboard (3)]
//!     ↳ Integrated Camera                         id=9    [slave  keyboard (3)]
//!     ↳ AT Translated Set 2 keyboard              id=12   [slave  keyboard (3)]
//!     ↳ ThinkPad Extra Buttons                    id=15   [slave  keyboard (3)]
//! ```
//!
//! By default, GDK will automatically listen for events coming from all master devices, setting the
//! Device for all events coming from input devices. Events containing device information are
//! GDK_MOTION_NOTIFY, GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_3BUTTON_PRESS, GDK_BUTTON_RELEASE,
//! GDK_SCROLL, GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_ENTER_NOTIFY, GDK_LEAVE_NOTIFY, GDK_FOCUS_CHANGE,
//! GDK_PROXIMITY_IN, GDK_PROXIMITY_OUT, GDK_DRAG_ENTER, GDK_DRAG_LEAVE, GDK_DRAG_MOTION,
//! GDK_DRAG_STATUS, GDK_DROP_START, GDK_DROP_FINISHED and GDK_GRAB_BROKEN. When dealing with an event
//! on a master device, it is possible to get the source (slave) device that the event originated from
//! via Event::get_source_device().
//!
//! On a standard session, all physical devices are connected by default to the "Virtual Core
//! Pointer/Keyboard" master devices, hence routing all events through these. This behavior is only
//! modified by device grabs, where the slave device is temporarily detached for as long as the grab is
//! held, and more permanently by user modifications to the device hierarchy.
//!
//! On certain application specific setups, it may make sense to detach a physical device from its
//! master pointer, and mapping it to an specific window. This can be achieved by the combination of
//! Device::grab() and Device::set_mode().
//!
//! In order to listen for events coming from devices other than a virtual device,
//! Window::set_device_events() must be called. Generally, this function can be used to modify the event
//! mask for any given device.
//!
//! Input devices may also provide additional information besides X/Y. For example, graphics tablets may
//! also provide pressure and X/Y tilt information. This information is device-dependent, and may be
//! queried through Device::get_axis(). In multidevice mode, virtual devices will change axes in order to
//! always represent the physical device that is routing events through it. Whenever the physical device
//! changes, the “n-axes” property will be notified, and Device::list_axes() will return the new device
//! axes.
//!
//! Devices may also have associated “keys” or macro buttons. Such keys can be globally set to map into
//! normal X keyboard events. The mapping is set using Device::set_key().

use glib::translate::*;
use glib::types::{StaticType, Type};
use device::Device;
use display::Display;
use object::Object;
use ffi;

pub type DeviceManager = Object<ffi::GdkDeviceManager>;

impl StaticType for DeviceManager {
    fn static_type() -> Type { unsafe { from_glib(ffi::gdk_device_manager_get_type()) } }
}

impl DeviceManager {
    /// Disables multidevice support in GDK. This call must happen prior to Display::open(),
    /// gtk::init(), gtk::init_with_args() or gtk::init_check() in order to take effect.
    ///
    /// Most common GTK+ applications won’t ever need to call this. Only applications that do
    /// mixed GDK/Xlib calls could want to disable multidevice support if such Xlib code deals
    /// with input devices in any way and doesn’t observe the presence of XInput 2.
    pub fn disable_multidevice() {
        unsafe { ffi::gdk_disable_multidevice() }
    }

    /// Gets the Display associated to `self`.
    pub fn get_display(&self) -> Option<Display> {
        unsafe { from_glib_none(ffi::gdk_device_manager_get_display(self.to_glib_none().0)) }
    }

    /// Returns the client pointer, that is, the master pointer that acts as the core pointer
    /// for this application. In X11, window managers may change this depending on the
    /// interaction pattern under the presence of several pointers.
    ///
    /// You should use this function seldomly, only in code that isn’t triggered by a Event and
    /// there aren’t other means to get a meaningful Device to operate on.
    pub fn get_client_pointer(&self) -> Device {
        unsafe {
            from_glib_none(
                ffi::gdk_device_manager_get_client_pointer(self.to_glib_none().0))
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add more candidates to the full-resolution search<commit_after><|endoftext|>


<commit_before>use std::ptr;

use mem;
use os;

pub struct SemiSpace {
    start: *const u8,
    end: *const u8,
    free: *const u8,
}

impl SemiSpace {
    fn new(size: usize) -> SemiSpace {
        let size = mem::align_usize(size, os::page_size() as usize);
        let ptr = os::mmap(size, os::Writable);

        if ptr.is_null() {
            panic!("could not allocate semi space of size {}", size);
        }

        SemiSpace {
            start: ptr,
            end: unsafe { ptr.offset(size as isize) },
            free: ptr,
        }
    }

    fn allocate(&mut self, size: usize) -> *const u8 {
        if self.end as usize - self.free as usize > size {
            let next = unsafe { self.free.offset(size as isize) };
            let addr = self.free;
            self.free = next;

            addr

        } else {
            ptr::null()
        }
    }
}

impl Drop for SemiSpace {
    fn drop(&mut self) {
        let size = self.end as usize - self.start as usize;
        os::munmap(self.start, size);
    }
}<commit_msg>gc: rename free to next<commit_after>use std::ptr;

use mem;
use os;

pub struct SemiSpace {
    start: *const u8,
    end: *const u8,
    next: *const u8,
}

impl SemiSpace {
    fn new(size: usize) -> SemiSpace {
        let size = mem::align_usize(size, os::page_size() as usize);
        let ptr = os::mmap(size, os::Writable);

        if ptr.is_null() {
            panic!("could not allocate semi space of size {}", size);
        }

        SemiSpace {
            start: ptr,
            end: unsafe { ptr.offset(size as isize) },
            next: ptr,
        }
    }

    fn allocate(&mut self, size: usize) -> *const u8 {
        if self.end as usize - self.next as usize > size {
            let next = unsafe { self.next.offset(size as isize) };
            let addr = self.next;
            self.next = next;

            addr

        } else {
            ptr::null()
        }
    }
}

impl Drop for SemiSpace {
    fn drop(&mut self) {
        let size = self.end as usize - self.start as usize;
        os::munmap(self.start, size);
    }
}<|endoftext|>


<commit_before>use std::fs;
use std::io::prelude::*;
use std::io;
use std::path::PathBuf;
use std::process;

pub fn create_profile_source(shim_dir: &PathBuf,
                             groonga_dir: &String,
                             install_dir: &PathBuf)
                             -> Result<(), io::Error> {
    if shim_dir.join("source-groonga.ps1").exists() {
        fs::remove_file(shim_dir.join("source-groonga.ps1")).unwrap();
    }
    let mut f = fs::File::create(shim_dir.join("source-groonga.ps1").to_str().unwrap())
        .expect("Could not create a powershell setting file.");
    let installed_groonga = install_dir.join(groonga_dir)
        .join("bin");
    if !installed_groonga.exists() {
        println!("Specified version is not installed.");
        process::exit(1);
    }
    let contents = format!("$Env:Path = \"{};\" + $Env:Path",
                           installed_groonga.display());
    match f.write_all(&contents.as_bytes()) {
        Ok(_) => return Ok(()),
        Err(e) => println!("{}", e),
    }
    f.sync_data()
}
<commit_msg>Handle remove_file error<commit_after>use std::fs;
use std::io::prelude::*;
use std::io;
use std::path::PathBuf;
use std::process;

pub fn create_profile_source(shim_dir: &PathBuf,
                             groonga_dir: &String,
                             install_dir: &PathBuf)
                             -> Result<(), io::Error> {
    if shim_dir.join("source-groonga.ps1").exists() {
        let _ = try!(fs::remove_file(shim_dir.join("source-groonga.ps1")));
    }
    let mut f = fs::File::create(shim_dir.join("source-groonga.ps1").to_str().unwrap())
        .expect("Could not create a powershell setting file.");
    let installed_groonga = install_dir.join(groonga_dir)
        .join("bin");
    if !installed_groonga.exists() {
        println!("Specified version is not installed.");
        process::exit(1);
    }
    let contents = format!("$Env:Path = \"{};\" + $Env:Path",
                           installed_groonga.display());
    match f.write_all(&contents.as_bytes()) {
        Ok(_) => return Ok(()),
        Err(e) => println!("{}", e),
    }
    f.sync_data()
}
<|endoftext|>


<commit_before>//! This crate contains a high-level abstraction for reading and manipulating
//! DICOM objects.
//! At this level, objects are comparable to a dictionary of elements,
//! in which some of them can have DICOM objects themselves.
//! The end user should prefer using this abstraction when dealing with DICOM
//! objects.
//!
//! # Examples
//!
//! Loading a file and reading some attributes by their standard alias:
//!
//! ```no_run
//! use dicom_object::open_file;
//! # use dicom_object::Result;
//! # fn foo() -> Result<()> {
//! let obj = open_file("0001.dcm")?;
//! let patient_name = obj.element_by_name("PatientName")?.to_str()?;
//! let modality = obj.element_by_name("Modality")?.to_str()?;
//! # Ok(())
//! # }
//! ```
//!
//! Elements can also be fetched by tag:
//!
//! ```
//! # use dicom_object::{DicomObject, Result, Tag};
//! # fn something<T: DicomObject>(obj: T) -> Result<()> {
//! let e = obj.element(Tag(0x0002, 0x0002))?;
//! # Ok(())
//! # }
//! ```
//!
pub mod file;
pub mod loader;
pub mod mem;
pub mod meta;
pub mod pixeldata;
pub mod tokens;

mod util;

pub use crate::file::{from_reader, open_file};
pub use crate::meta::FileMetaTable;
pub use dicom_core::Tag;
pub use dicom_dictionary_std::StandardDataDictionary;
pub use dicom_parser::error::{Error, Result};

/// The default implementation of a root DICOM object.
pub type DefaultDicomObject = RootDicomObject<mem::InMemDicomObject<StandardDataDictionary>>;

use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
use dicom_core::header::Header;
use dicom_encoding::{transfer_syntax::TransferSyntaxIndex, text::SpecificCharacterSet};
use dicom_parser::dataset::{DataSetWriter, IntoTokens};
use dicom_transfer_syntax_registry::TransferSyntaxRegistry;

/// Trait type for a DICOM object.
/// This is a high-level abstraction where an object is accessed and
/// manipulated as dictionary of entries indexed by tags, which in
/// turn may contain a DICOM object.
///
/// This trait interface is experimental and prone to sudden changes.
pub trait DicomObject {
    type Element: Header;

    /// Retrieve a particular DICOM element by its tag.
    fn element(&self, tag: Tag) -> Result<Self::Element>;

    /// Retrieve a particular DICOM element by its name.
    fn element_by_name(&self, name: &str) -> Result<Self::Element>;

    /// Retrieve the processed meta information table, if available.
    ///
    /// This table will generally not be reachable from children objects
    /// in another object with a valid meta table. As such, it is recommended
    /// for this method to be called at the root of a DICOM object.
    fn meta(&self) -> Option<&FileMetaTable> {
        None
    }
}

/** A root DICOM object contains additional meta information about the object
 * (such as the DICOM file's meta header).
 */
#[derive(Debug, Clone, PartialEq)]
pub struct RootDicomObject<T> {
    meta: FileMetaTable,
    obj: T,
}

impl<T> RootDicomObject<T> {
    /// Retrieve the processed meta header table.
    pub fn meta(&self) -> &FileMetaTable {
        &self.meta
    }

    /// Retrieve the inner DICOM object structure, discarding the meta table.
    pub fn into_inner(self) -> T {
        self.obj
    }
}

impl<T> RootDicomObject<T>
where
    for<'a> &'a T: IntoTokens,
{
    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let file = File::create(path)?;
        let mut to = BufWriter::new(file);

        // write preamble
        to.write(&[0_u8; 128][..])?;

        // write magic sequence
        to.write(b"DICM")?;

        // write meta group
        self.meta.write(&mut to)?;

        // prepare encoder
        let registry = TransferSyntaxRegistry::default();
        let ts = registry
            .get(&self.meta.transfer_syntax)
            .ok_or_else(|| Error::UnsupportedTransferSyntax)?;
        let cs = SpecificCharacterSet::Default;
        let mut dset_writer = DataSetWriter::with_ts_cs(to, ts, cs)?;

        // write object

        dset_writer.write_sequence((&self.obj).into_tokens())?;

        Ok(())
    }
}

impl<T> ::std::ops::Deref for RootDicomObject<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.obj
    }
}

impl<T> ::std::ops::DerefMut for RootDicomObject<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.obj
    }
}

impl<T> DicomObject for RootDicomObject<T>
where
    T: DicomObject,
{
    type Element = <T as DicomObject>::Element;

    fn element(&self, tag: Tag) -> Result<Self::Element> {
        self.obj.element(tag)
    }

    fn element_by_name(&self, name: &str) -> Result<Self::Element> {
        self.obj.element_by_name(name)
    }

    fn meta(&self) -> Option<&FileMetaTable> {
        Some(&self.meta)
    }
}

impl<'a, T: 'a> DicomObject for &'a RootDicomObject<T>
where
    T: DicomObject,
{
    type Element = <T as DicomObject>::Element;

    fn element(&self, tag: Tag) -> Result<Self::Element> {
        self.obj.element(tag)
    }

    fn element_by_name(&self, name: &str) -> Result<Self::Element> {
        self.obj.element_by_name(name)
    }
}

impl<T> IntoIterator for RootDicomObject<T>
where
    T: IntoIterator,
{
    type Item = <T as IntoIterator>::Item;
    type IntoIter = <T as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.obj.into_iter()
    }
}

#[cfg(test)]
mod tests {
    use crate::RootDicomObject;
    use crate::meta::FileMetaTableBuilder;

    #[test]
    fn smoke_test() {
        let meta = FileMetaTableBuilder::new()
            .transfer_syntax(dicom_transfer_syntax_registry::entries::EXPLICIT_VR_LITTLE_ENDIAN.uid().to_owned() + "\0")
            .media_storage_sop_class_uid("1.2.840.10008.5.1.4.1.1.1\0".to_owned())
            .media_storage_sop_instance_uid("1.2.3.456\0".to_owned())
            .implementation_class_uid("1.2.345.6.7890.1.234".to_owned())
            .build()
            .unwrap();
        let obj = RootDicomObject::new_empty_with_meta(
            meta);

        obj.write_to_file(".smoke-test.dcm").unwrap();
        let _ = std::fs::remove_file(".smoke-test.dcm");
    }
}
<commit_msg>fix RootDicomObject::write_to_file<commit_after>//! This crate contains a high-level abstraction for reading and manipulating
//! DICOM objects.
//! At this level, objects are comparable to a dictionary of elements,
//! in which some of them can have DICOM objects themselves.
//! The end user should prefer using this abstraction when dealing with DICOM
//! objects.
//!
//! # Examples
//!
//! Loading a file and reading some attributes by their standard alias:
//!
//! ```no_run
//! use dicom_object::open_file;
//! # use dicom_object::Result;
//! # fn foo() -> Result<()> {
//! let obj = open_file("0001.dcm")?;
//! let patient_name = obj.element_by_name("PatientName")?.to_str()?;
//! let modality = obj.element_by_name("Modality")?.to_str()?;
//! # Ok(())
//! # }
//! ```
//!
//! Elements can also be fetched by tag:
//!
//! ```
//! # use dicom_object::{DicomObject, Result, Tag};
//! # fn something<T: DicomObject>(obj: T) -> Result<()> {
//! let e = obj.element(Tag(0x0002, 0x0002))?;
//! # Ok(())
//! # }
//! ```
//!
pub mod file;
pub mod loader;
pub mod mem;
pub mod meta;
pub mod pixeldata;
pub mod tokens;

mod util;

pub use crate::file::{from_reader, open_file};
pub use crate::meta::FileMetaTable;
pub use dicom_core::Tag;
pub use dicom_dictionary_std::StandardDataDictionary;
pub use dicom_parser::error::{Error, Result};

/// The default implementation of a root DICOM object.
pub type DefaultDicomObject = RootDicomObject<mem::InMemDicomObject<StandardDataDictionary>>;

use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
use dicom_core::header::Header;
use dicom_encoding::{transfer_syntax::TransferSyntaxIndex, text::SpecificCharacterSet};
use dicom_parser::dataset::{DataSetWriter, IntoTokens};
use dicom_transfer_syntax_registry::TransferSyntaxRegistry;

/// Trait type for a DICOM object.
/// This is a high-level abstraction where an object is accessed and
/// manipulated as dictionary of entries indexed by tags, which in
/// turn may contain a DICOM object.
///
/// This trait interface is experimental and prone to sudden changes.
pub trait DicomObject {
    type Element: Header;

    /// Retrieve a particular DICOM element by its tag.
    fn element(&self, tag: Tag) -> Result<Self::Element>;

    /// Retrieve a particular DICOM element by its name.
    fn element_by_name(&self, name: &str) -> Result<Self::Element>;

    /// Retrieve the processed meta information table, if available.
    ///
    /// This table will generally not be reachable from children objects
    /// in another object with a valid meta table. As such, it is recommended
    /// for this method to be called at the root of a DICOM object.
    fn meta(&self) -> Option<&FileMetaTable> {
        None
    }
}

/** A root DICOM object contains additional meta information about the object
 * (such as the DICOM file's meta header).
 */
#[derive(Debug, Clone, PartialEq)]
pub struct RootDicomObject<T> {
    meta: FileMetaTable,
    obj: T,
}

impl<T> RootDicomObject<T> {
    /// Retrieve the processed meta header table.
    pub fn meta(&self) -> &FileMetaTable {
        &self.meta
    }

    /// Retrieve the inner DICOM object structure, discarding the meta table.
    pub fn into_inner(self) -> T {
        self.obj
    }
}

impl<T> RootDicomObject<T>
where
    for<'a> &'a T: IntoTokens,
{
    pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let file = File::create(path)?;
        let mut to = BufWriter::new(file);

        // write preamble
        to.write_all(&[0_u8; 128][..])?;

        // write magic sequence
        to.write_all(b"DICM")?;

        // write meta group
        self.meta.write(&mut to)?;

        // prepare encoder
        let registry = TransferSyntaxRegistry::default();
        let ts = registry
            .get(&self.meta.transfer_syntax)
            .ok_or_else(|| Error::UnsupportedTransferSyntax)?;
        let cs = SpecificCharacterSet::Default;
        let mut dset_writer = DataSetWriter::with_ts_cs(to, ts, cs)?;

        // write object

        dset_writer.write_sequence((&self.obj).into_tokens())?;

        Ok(())
    }
}

impl<T> ::std::ops::Deref for RootDicomObject<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.obj
    }
}

impl<T> ::std::ops::DerefMut for RootDicomObject<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.obj
    }
}

impl<T> DicomObject for RootDicomObject<T>
where
    T: DicomObject,
{
    type Element = <T as DicomObject>::Element;

    fn element(&self, tag: Tag) -> Result<Self::Element> {
        self.obj.element(tag)
    }

    fn element_by_name(&self, name: &str) -> Result<Self::Element> {
        self.obj.element_by_name(name)
    }

    fn meta(&self) -> Option<&FileMetaTable> {
        Some(&self.meta)
    }
}

impl<'a, T: 'a> DicomObject for &'a RootDicomObject<T>
where
    T: DicomObject,
{
    type Element = <T as DicomObject>::Element;

    fn element(&self, tag: Tag) -> Result<Self::Element> {
        self.obj.element(tag)
    }

    fn element_by_name(&self, name: &str) -> Result<Self::Element> {
        self.obj.element_by_name(name)
    }
}

impl<T> IntoIterator for RootDicomObject<T>
where
    T: IntoIterator,
{
    type Item = <T as IntoIterator>::Item;
    type IntoIter = <T as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.obj.into_iter()
    }
}

#[cfg(test)]
mod tests {
    use crate::RootDicomObject;
    use crate::meta::FileMetaTableBuilder;

    #[test]
    fn smoke_test() {
        let meta = FileMetaTableBuilder::new()
            .transfer_syntax(dicom_transfer_syntax_registry::entries::EXPLICIT_VR_LITTLE_ENDIAN.uid().to_owned() + "\0")
            .media_storage_sop_class_uid("1.2.840.10008.5.1.4.1.1.1\0".to_owned())
            .media_storage_sop_instance_uid("1.2.3.456\0".to_owned())
            .implementation_class_uid("1.2.345.6.7890.1.234".to_owned())
            .build()
            .unwrap();
        let obj = RootDicomObject::new_empty_with_meta(
            meta);

        obj.write_to_file(".smoke-test.dcm").unwrap();
        let _ = std::fs::remove_file(".smoke-test.dcm");
    }
}
<|endoftext|>


<commit_before>use std::time::{Duration, SystemTime, Instant};
use std::convert::TryFrom;

use crate::stacked_borrows::Tag;
use crate::*;
use helpers::{immty_from_int_checked, immty_from_uint_checked};

use rustc_middle::ty::layout::LayoutOf;

/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
    time.duration_since(SystemTime::UNIX_EPOCH)
        .map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn clock_gettime(
        &mut self,
        clk_id_op: OpTy<'tcx, Tag>,
        tp_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("linux", "clock_gettime");
        this.check_no_isolation("clock_gettime")?;

        let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
        let tp = this.deref_operand(tp_op)?;

        let duration = if clk_id == this.eval_libc_i32("CLOCK_REALTIME")? {
            system_time_to_duration(&SystemTime::now())?
        } else if clk_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
            // Absolute time does not matter, only relative time does, so we can just
            // use our own time anchor here.
            Instant::now().duration_since(this.machine.time_anchor)
        } else {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        };

        let tv_sec = duration.as_secs();
        let tv_nsec = duration.subsec_nanos();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_nsec, this.libc_ty_layout("c_long")?)?,
        ];

        this.write_packed_immediates(tp, &imms)?;

        Ok(0)
    }

    fn gettimeofday(
        &mut self,
        tv_op: OpTy<'tcx, Tag>,
        tz_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("macos", "gettimeofday");
        this.check_no_isolation("gettimeofday")?;

        // Using tz is obsolete and should always be null
        let tz = this.read_scalar(tz_op)?.not_undef()?;
        if !this.is_null(tz)? {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        }

        let tv = this.deref_operand(tv_op)?;

        let duration = system_time_to_duration(&SystemTime::now())?;
        let tv_sec = duration.as_secs();
        let tv_usec = duration.subsec_micros();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_usec, this.libc_ty_layout("suseconds_t")?)?,
        ];

        this.write_packed_immediates(tv, &imms)?;

        Ok(0)
    }

    #[allow(non_snake_case)]
    fn GetSystemTimeAsFileTime(&mut self, LPFILETIME_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "GetSystemTimeAsFileTime");
        this.check_no_isolation("GetSystemTimeAsFileTime")?;

        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?;
        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?;
        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?;
        let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC;
        let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC;

        let duration = system_time_to_duration(&SystemTime::now())?
            .checked_add(Duration::from_secs(SECONDS_TO_UNIX_EPOCH))
            .unwrap();
        let duration_ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL))
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 ticks are not supported"))?;

        let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap();
        let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap();
        let DWORD_tylayout = this.layout_of(this.tcx.types.u32)?;
        let imms = [
            immty_from_uint_checked(dwLowDateTime, DWORD_tylayout)?,
            immty_from_uint_checked(dwHighDateTime, DWORD_tylayout)?,
        ];
        this.write_packed_immediates(this.deref_operand(LPFILETIME_op)?, &imms)?;
        Ok(())
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceCounter(&mut self, lpPerformanceCount_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceCounter");
        this.check_no_isolation("QueryPerformanceCounter")?;

        // QPC uses a hardware counter as its basis.
        // Miri will emulate a counter with a resolution of 1 nanosecond.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        let qpc = i64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported"))?;
        this.write_scalar(Scalar::from_i64(qpc), this.deref_operand(lpPerformanceCount_op)?.into())?;
        Ok(-1) // return non-zero on success
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceFrequency(&mut self, lpFrequency_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceFrequency");
        this.check_no_isolation("QueryPerformanceFrequency")?;

        // Retrieves the frequency of the hardware performance counter.
        // The frequency of the performance counter is fixed at system boot and
        // is consistent across all processors.
        // Miri will assume that the frequency of
        // the machine's hardware performance counter is 1 GHz ( = 1 x 10^9 Hz).
        this.write_scalar(Scalar::from_i64(1_000_000_000), this.deref_operand(lpFrequency_op)?.into())?;
        Ok(-1) // Return non-zero on success
    }

    fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
        let this = self.eval_context_ref();

        this.assert_target_os("macos", "mach_absolute_time");
        this.check_no_isolation("mach_absolute_time")?;

        // This returns a u64, with time units determined dynamically by `mach_timebase_info`.
        // We return plain nanoseconds.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        u64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported").into())
    }
}
<commit_msg>Update comments in src/shims/time.rs<commit_after>use std::time::{Duration, SystemTime, Instant};
use std::convert::TryFrom;

use crate::stacked_borrows::Tag;
use crate::*;
use helpers::{immty_from_int_checked, immty_from_uint_checked};

use rustc_middle::ty::layout::LayoutOf;

/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
    time.duration_since(SystemTime::UNIX_EPOCH)
        .map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn clock_gettime(
        &mut self,
        clk_id_op: OpTy<'tcx, Tag>,
        tp_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("linux", "clock_gettime");
        this.check_no_isolation("clock_gettime")?;

        let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
        let tp = this.deref_operand(tp_op)?;

        let duration = if clk_id == this.eval_libc_i32("CLOCK_REALTIME")? {
            system_time_to_duration(&SystemTime::now())?
        } else if clk_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
            // Absolute time does not matter, only relative time does, so we can just
            // use our own time anchor here.
            Instant::now().duration_since(this.machine.time_anchor)
        } else {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        };

        let tv_sec = duration.as_secs();
        let tv_nsec = duration.subsec_nanos();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_nsec, this.libc_ty_layout("c_long")?)?,
        ];

        this.write_packed_immediates(tp, &imms)?;

        Ok(0)
    }

    fn gettimeofday(
        &mut self,
        tv_op: OpTy<'tcx, Tag>,
        tz_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("macos", "gettimeofday");
        this.check_no_isolation("gettimeofday")?;

        // Using tz is obsolete and should always be null
        let tz = this.read_scalar(tz_op)?.not_undef()?;
        if !this.is_null(tz)? {
            let einval = this.eval_libc("EINVAL")?;
            this.set_last_error(einval)?;
            return Ok(-1);
        }

        let tv = this.deref_operand(tv_op)?;

        let duration = system_time_to_duration(&SystemTime::now())?;
        let tv_sec = duration.as_secs();
        let tv_usec = duration.subsec_micros();

        let imms = [
            immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
            immty_from_int_checked(tv_usec, this.libc_ty_layout("suseconds_t")?)?,
        ];

        this.write_packed_immediates(tv, &imms)?;

        Ok(0)
    }

    #[allow(non_snake_case)]
    fn GetSystemTimeAsFileTime(&mut self, LPFILETIME_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "GetSystemTimeAsFileTime");
        this.check_no_isolation("GetSystemTimeAsFileTime")?;

        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?;
        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?;
        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?;
        let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC;
        let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC;

        let duration = system_time_to_duration(&SystemTime::now())?
            .checked_add(Duration::from_secs(SECONDS_TO_UNIX_EPOCH))
            .unwrap();
        let duration_ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL))
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 ticks are not supported"))?;

        let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap();
        let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap();
        let DWORD_tylayout = this.layout_of(this.tcx.types.u32)?;
        let imms = [
            immty_from_uint_checked(dwLowDateTime, DWORD_tylayout)?,
            immty_from_uint_checked(dwHighDateTime, DWORD_tylayout)?,
        ];
        this.write_packed_immediates(this.deref_operand(LPFILETIME_op)?, &imms)?;
        Ok(())
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceCounter(&mut self, lpPerformanceCount_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceCounter");
        this.check_no_isolation("QueryPerformanceCounter")?;

        // QueryPerformanceCounter uses a hardware counter as its basis.
        // Miri will emulate a counter with a resolution of 1 nanosecond.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        let qpc = i64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported"))?;
        this.write_scalar(Scalar::from_i64(qpc), this.deref_operand(lpPerformanceCount_op)?.into())?;
        Ok(-1) // return non-zero on success
    }

    #[allow(non_snake_case)]
    fn QueryPerformanceFrequency(&mut self, lpFrequency_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.assert_target_os("windows", "QueryPerformanceFrequency");
        this.check_no_isolation("QueryPerformanceFrequency")?;

        // Retrieves the frequency of the hardware performance counter.
        // The frequency of the performance counter is fixed at system boot and
        // is consistent across all processors.
        // Miri will assume that the frequency of
        // the machine's hardware performance counter is 1 GHz ( = 1 x 10^9 Hz).
        this.write_scalar(Scalar::from_i64(1_000_000_000), this.deref_operand(lpFrequency_op)?.into())?;
        Ok(-1) // Return non-zero on success
    }

    fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
        let this = self.eval_context_ref();

        this.assert_target_os("macos", "mach_absolute_time");
        this.check_no_isolation("mach_absolute_time")?;

        // This returns a u64, with time units determined dynamically by `mach_timebase_info`.
        // We return plain nanoseconds.
        let duration = Instant::now().duration_since(this.machine.time_anchor);
        u64::try_from(duration.as_nanos())
            .map_err(|_| err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported").into())
    }
}
<|endoftext|>


<commit_before>use super::*;
use crate::norm::Norm;
use num_traits::One;
use std::iter::*;

pub struct Arnoldi<A, S, F, Ortho>
where
    A: Scalar,
    S: DataMut<Elem = A>,
    F: Fn(&mut ArrayBase<S, Ix1>),
    Ortho: Orthogonalizer<Elem = A>,
{
    a: F,
    v: ArrayBase<S, Ix1>,
    ortho: Ortho,
    /// Coefficients
    h: Vec<Array1<A>>,
}

impl<A, S, F, Ortho> Arnoldi<A, S, F, Ortho>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
    F: Fn(&mut ArrayBase<S, Ix1>),
    Ortho: Orthogonalizer<Elem = A>,
{
    pub fn new(a: F, mut v: ArrayBase<S, Ix1>, mut ortho: Ortho) -> Self {
        assert_eq!(ortho.len(), 0);
        assert!(ortho.tolerance() < One::one());
        // normalize before append because |v| may be smaller than ortho.tolerance()
        let norm = v.norm_l2();
        azip!(mut v(&mut v) in { *v = v.div_real(norm) });
        ortho.append(v.view());
        Arnoldi {
            a,
            v,
            ortho,
            h: Vec::new(),
        }
    }

    /// Dimension of Krylov subspace
    pub fn dim(&self) -> usize {
        self.ortho.len()
    }

    /// Iterate until convergent
    pub fn complete(mut self) -> (Q<A>, H<A>) {
        for _ in &mut self {} // execute iteration until convergent
        let q = self.ortho.get_q();
        let n = self.dim();
        let mut h = Array2::zeros((n, n).f());
        for (i, hc) in self.h.iter().enumerate() {
            let m = std::cmp::max(n, i + 1);
            for j in 0..m {
                h[(j, i)] = hc[j];
            }
        }
        (q, h)
    }
}

impl<A, S, F, Ortho> Iterator for Arnoldi<A, S, F, Ortho>
where
    A: Scalar,
    S: DataMut<Elem = A>,
    F: Fn(&mut ArrayBase<S, Ix1>),
    Ortho: Orthogonalizer<Elem = A>,
{
    type Item = Array1<A>;

    fn next(&mut self) -> Option<Self::Item> {
        (self.a)(&mut self.v);
        let result = self.ortho.div_append(&mut self.v);
        azip!(mut v(&mut self.v) in { *v = v.div_real(result.residual_norm()) });
        if result.is_dependent() {
            None
        } else {
            let coef = result.into_coeff();
            self.h.push(coef.clone());
            Some(coef)
        }
    }
}

/// Interpret a matrix as a linear operator
pub fn mul_mat<A, S1, S2>(a: ArrayBase<S1, Ix2>) -> impl Fn(&mut ArrayBase<S2, Ix1>)
where
    A: Scalar,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    let (n, m) = a.dim();
    assert_eq!(n, m, "Input matrix must be square");
    move |x| {
        assert_eq!(m, x.len(), "Input matrix and vector sizes mismatch");
        let ax = a.dot(x);
        azip!(mut x(x), ax in { *x = ax });
    }
}

pub fn arnoldi_householder<A, S1, S2>(a: ArrayBase<S1, Ix2>, v: ArrayBase<S2, Ix1>, tol: A::Real) -> (Q<A>, H<A>)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    let householder = Householder::new(v.len(), tol);
    Arnoldi::new(mul_mat(a), v, householder).complete()
}

pub fn arnoldi_mgs<A, S1, S2>(a: ArrayBase<S1, Ix2>, v: ArrayBase<S2, Ix1>, tol: A::Real) -> (Q<A>, H<A>)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    let mgs = MGS::new(v.len(), tol);
    Arnoldi::new(mul_mat(a), v, mgs).complete()
}
<commit_msg>Fill documents<commit_after>use super::*;
use crate::norm::Norm;
use num_traits::One;
use std::iter::*;

/// Execute Arnodi iteration as Rust iterator
///
/// - [Arnoldi iteration - Wikipedia](https://en.wikipedia.org/wiki/Arnoldi_iteration)
///
pub struct Arnoldi<A, S, F, Ortho>
where
    A: Scalar,
    S: DataMut<Elem = A>,
    F: Fn(&mut ArrayBase<S, Ix1>),
    Ortho: Orthogonalizer<Elem = A>,
{
    a: F,
    /// Next vector (normalized `|v|=1`)
    v: ArrayBase<S, Ix1>,
    /// Orthogonalizer
    ortho: Ortho,
    /// Coefficients to be composed into H-matrix
    h: Vec<Array1<A>>,
}

impl<A, S, F, Ortho> Arnoldi<A, S, F, Ortho>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
    F: Fn(&mut ArrayBase<S, Ix1>),
    Ortho: Orthogonalizer<Elem = A>,
{
    pub fn new(a: F, mut v: ArrayBase<S, Ix1>, mut ortho: Ortho) -> Self {
        assert_eq!(ortho.len(), 0);
        assert!(ortho.tolerance() < One::one());
        // normalize before append because |v| may be smaller than ortho.tolerance()
        let norm = v.norm_l2();
        azip!(mut v(&mut v) in { *v = v.div_real(norm) });
        ortho.append(v.view());
        Arnoldi {
            a,
            v,
            ortho,
            h: Vec::new(),
        }
    }

    /// Dimension of Krylov subspace
    pub fn dim(&self) -> usize {
        self.ortho.len()
    }

    /// Iterate until convergent
    pub fn complete(mut self) -> (Q<A>, H<A>) {
        for _ in &mut self {} // execute iteration until convergent
        let q = self.ortho.get_q();
        let n = self.dim();
        let mut h = Array2::zeros((n, n).f());
        for (i, hc) in self.h.iter().enumerate() {
            let m = std::cmp::max(n, i + 1);
            for j in 0..m {
                h[(j, i)] = hc[j];
            }
        }
        (q, h)
    }
}

impl<A, S, F, Ortho> Iterator for Arnoldi<A, S, F, Ortho>
where
    A: Scalar,
    S: DataMut<Elem = A>,
    F: Fn(&mut ArrayBase<S, Ix1>),
    Ortho: Orthogonalizer<Elem = A>,
{
    type Item = Array1<A>;

    fn next(&mut self) -> Option<Self::Item> {
        (self.a)(&mut self.v);
        let result = self.ortho.div_append(&mut self.v);
        azip!(mut v(&mut self.v) in { *v = v.div_real(result.residual_norm()) });
        if result.is_dependent() {
            None
        } else {
            let coef = result.into_coeff();
            self.h.push(coef.clone());
            Some(coef)
        }
    }
}

/// Interpret a matrix as a linear operator
pub fn mul_mat<A, S1, S2>(a: ArrayBase<S1, Ix2>) -> impl Fn(&mut ArrayBase<S2, Ix1>)
where
    A: Scalar,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    let (n, m) = a.dim();
    assert_eq!(n, m, "Input matrix must be square");
    move |x| {
        assert_eq!(m, x.len(), "Input matrix and vector sizes mismatch");
        let ax = a.dot(x);
        azip!(mut x(x), ax in { *x = ax });
    }
}

/// Utility to execute Arnoldi iteration with Householder reflection
pub fn arnoldi_householder<A, S1, S2>(a: ArrayBase<S1, Ix2>, v: ArrayBase<S2, Ix1>, tol: A::Real) -> (Q<A>, H<A>)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    let householder = Householder::new(v.len(), tol);
    Arnoldi::new(mul_mat(a), v, householder).complete()
}

/// Utility to execute Arnoldi iteration with modified Gram-Schmit orthogonalizer
pub fn arnoldi_mgs<A, S1, S2>(a: ArrayBase<S1, Ix2>, v: ArrayBase<S2, Ix1>, tol: A::Real) -> (Q<A>, H<A>)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    let mgs = MGS::new(v.len(), tol);
    Arnoldi::new(mul_mat(a), v, mgs).complete()
}
<|endoftext|>


<commit_before>pub use self::os::{LOG_PID};
pub use self::os::{LOG_CONS};
pub use self::os::{LOG_NDELAY};
pub use self::os::{LOG_ODELAY};
pub use self::os::{LOG_NOWAIT};
pub use self::os::{LOG_KERN};
pub use self::os::{LOG_USER};
pub use self::os::{LOG_MAIL};
pub use self::os::{LOG_NEWS};
pub use self::os::{LOG_UUCP};
pub use self::os::{LOG_DAEMON};
pub use self::os::{LOG_AUTH};
pub use self::os::{LOG_CRON};
pub use self::os::{LOG_LPR};
pub use self::os::{LOG_LOCAL0};
pub use self::os::{LOG_LOCAL1};
pub use self::os::{LOG_LOCAL2};
pub use self::os::{LOG_LOCAL3};
pub use self::os::{LOG_LOCAL4};
pub use self::os::{LOG_LOCAL5};
pub use self::os::{LOG_LOCAL6};
pub use self::os::{LOG_LOCAL7};
pub use self::os::{LOG_EMERG};
pub use self::os::{LOG_ALERT};
pub use self::os::{LOG_CRIT};
pub use self::os::{LOG_ERR};
pub use self::os::{LOG_WARNING};
pub use self::os::{LOG_NOTICE};
pub use self::os::{LOG_INFO};
pub use self::os::{LOG_DEBUG};
pub use self::os::{LOG_MASK};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn closelog() {
    extern { fn closelog(); }
    unsafe { closelog(); }
}

pub fn openlog<T: ::NTStr>(ident: &T, option: ::int_t, facility: ::int_t) {
    extern { fn openlog(ident: *const ::char_t, option: ::int_t, facility: ::int_t); }
    unsafe { openlog(ident.as_ptr(), option, facility) }
}

pub fn setlogmask(mask: ::int_t) -> ::int_t {
    extern { fn setlogmask(mask: ::int_t) -> ::int_t; }
    unsafe { setlogmask(mask) }
}

extern "C" {
    pub fn syslog(pri: ::int_t, fmt: *const ::char_t, ...);
}
<commit_msg>syslog.h<commit_after>pub use self::os::{LOG_PID};
pub use self::os::{LOG_CONS};
pub use self::os::{LOG_NDELAY};
pub use self::os::{LOG_ODELAY};
pub use self::os::{LOG_NOWAIT};
pub use self::os::{LOG_KERN};
pub use self::os::{LOG_USER};
pub use self::os::{LOG_MAIL};
pub use self::os::{LOG_NEWS};
pub use self::os::{LOG_UUCP};
pub use self::os::{LOG_DAEMON};
pub use self::os::{LOG_AUTH};
pub use self::os::{LOG_CRON};
pub use self::os::{LOG_LPR};
pub use self::os::{LOG_LOCAL0};
pub use self::os::{LOG_LOCAL1};
pub use self::os::{LOG_LOCAL2};
pub use self::os::{LOG_LOCAL3};
pub use self::os::{LOG_LOCAL4};
pub use self::os::{LOG_LOCAL5};
pub use self::os::{LOG_LOCAL6};
pub use self::os::{LOG_LOCAL7};
pub use self::os::{LOG_EMERG};
pub use self::os::{LOG_ALERT};
pub use self::os::{LOG_CRIT};
pub use self::os::{LOG_ERR};
pub use self::os::{LOG_WARNING};
pub use self::os::{LOG_NOTICE};
pub use self::os::{LOG_INFO};
pub use self::os::{LOG_DEBUG};
pub use self::os::{LOG_MASK};

use {NTStr, char_t, int_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn closelog() {
    extern { fn closelog(); }
    unsafe { closelog(); }
}

pub fn openlog<T: NTStr>(ident: &T, option: int_t, facility: int_t) {
    extern { fn openlog(ident: *const char_t, option: int_t, facility: int_t); }
    unsafe { openlog(ident.as_ptr(), option, facility) }
}

pub fn setlogmask(mask: int_t) -> int_t {
    extern { fn setlogmask(mask: int_t) -> int_t; }
    unsafe { setlogmask(mask) }
}

extern {
    pub fn syslog(pri: int_t, fmt: *const char_t, ...);
}
<|endoftext|>


<commit_before>use super::raw;
use std::fmt;
use std::cell::RefCell;

pub struct Document<'d> {
    storage: &'d raw::Storage,
    connections: RefCell<&'d raw::Connections>,
}

impl<'d> Document<'d> {
    pub fn new(storage: &'d raw::Storage, connections: &'d raw::Connections) -> Document<'d> {
        Document {
            storage: storage,
            connections: RefCell::new(connections),
        }
    }

    fn wrap_element(&'d self, node: *mut raw::Element) -> Element<'d> {
        Element {
            document: self,
            node: node,
        }
    }

    pub fn create_element(&'d self, name: &str) -> Element<'d> {
        self.wrap_element(self.storage.create_element(name))
    }
}

pub struct Element<'d> {
    document: &'d Document<'d>,
    node: *mut raw::Element,
}

impl<'d> Element<'d> {
    fn node(&self) -> &raw::Element { unsafe { &*self.node } }

    pub fn name(&self) -> &str { self.node().name() }

    pub fn set_name(&self, name: &str) {
        self.document.storage.element_set_name(self.node, name)
    }

    pub fn parent(&'d self) -> Option<ParentOfChild<'d>> {
        let connections = self.document.connections.borrow();

        connections.element_parent(self.node).map(|n| {
            match n {
                raw::ElementPOC(n) => ElementPOC(self.document.wrap_element(n)),
            }
        })
    }

    pub fn append_child(&self, child: Element) {
        let connections = self.document.connections.borrow_mut();
        connections.append_element_child(self.node, child.node)
    }

    pub fn children(&'d self) -> Vec<ChildOfElement<'d>> {
        let connections = self.document.connections.borrow();
        // This is safe because we copy of the children, and the
        // children are never deallocated.
        unsafe {
            let raw_children = connections.element_children(self.node);
            raw_children.iter().map(|n| match n {
                &raw::ElementCOE(n) => ElementCOE(self.document.wrap_element(n)),
            }).collect()
        }
    }
}

impl<'d> PartialEq for Element<'d> {
    fn eq(&self, other: &Element<'d>) -> bool {
        self.node == other.node
    }
}

impl<'d> fmt::Show for Element<'d> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let node = unsafe { &* self.node };
        write!(f, "Element {{ name: {}  }}", node.name())
    }
}

#[deriving(PartialEq,Show)]
pub enum ChildOfElement<'d> {
    ElementCOE(Element<'d>)
}

impl<'d> ChildOfElement<'d> {
    pub fn element(self) -> Option<Element<'d>> {
        match self {
            ElementCOE(n) => Some(n),
        }
    }
}

#[deriving(PartialEq,Show)]
pub enum ParentOfChild<'d> {
    ElementPOC(Element<'d>),
}

#[cfg(test)]
mod test {
    use super::super::Package;
    use super::{ElementCOE};
    use super::{ElementPOC};

    #[test]
    fn elements_can_have_element_children() {
        let package = Package::new();
        let doc = package.as_document();

        let alpha = doc.create_element("alpha");
        let beta  = doc.create_element("beta");

        alpha.append_child(beta);

        let children = alpha.children();

        assert_eq!(children[0], ElementCOE(beta));
    }

    #[test]
    fn element_children_are_ordered() {
        let package = Package::new();
        let doc = package.as_document();

        let greek = doc.create_element("greek");
        let alpha = doc.create_element("alpha");
        let omega = doc.create_element("omega");

        greek.append_child(alpha);
        greek.append_child(omega);

        let children = greek.children();

        assert_eq!(children[0], ElementCOE(alpha));
        assert_eq!(children[1], ElementCOE(omega));
    }

    #[test]
    fn element_children_know_their_parent() {
        let package = Package::new();
        let doc = package.as_document();

        let alpha = doc.create_element("alpha");
        let beta  = doc.create_element("beta");

        alpha.append_child(beta);

        assert_eq!(Some(ElementPOC(alpha)), beta.parent());
    }

    #[test]
    fn changing_parent_of_element_removes_element_from_original_parent() {
        let package = Package::new();
        let doc = package.as_document();

        let parent1 = doc.create_element("parent1");
        let parent2 = doc.create_element("parent2");
        let child = doc.create_element("child");

        parent1.append_child(child);
        parent2.append_child(child);

        assert!(parent1.children().is_empty());
        assert_eq!(1, parent2.children().len());
    }

    #[test]
    fn elements_can_be_renamed() {
        let package = Package::new();
        let doc = package.as_document();

        let alpha = doc.create_element("alpha");
        alpha.set_name("beta");
        assert_eq!(alpha.name(), "beta");
    }
}
<commit_msg>Fat DOM elements belong to a document<commit_after>use super::raw;
use std::fmt;
use std::cell::RefCell;

pub struct Document<'d> {
    storage: &'d raw::Storage,
    connections: RefCell<&'d raw::Connections>,
}

impl<'d> Document<'d> {
    pub fn new(storage: &'d raw::Storage, connections: &'d raw::Connections) -> Document<'d> {
        Document {
            storage: storage,
            connections: RefCell::new(connections),
        }
    }

    fn wrap_element(&'d self, node: *mut raw::Element) -> Element<'d> {
        Element {
            document: self,
            node: node,
        }
    }

    pub fn create_element(&'d self, name: &str) -> Element<'d> {
        self.wrap_element(self.storage.create_element(name))
    }
}

impl<'d> PartialEq for Document<'d> {
    fn eq(&self, other: &Document<'d>) -> bool {
        self as *const Document == other as *const Document
    }
}

impl<'d> fmt::Show for Document<'d> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Document {{ {} }}", self as *const Document)
    }
}

pub struct Element<'d> {
    document: &'d Document<'d>,
    node: *mut raw::Element,
}

impl<'d> Element<'d> {
    fn node(&self) -> &raw::Element { unsafe { &*self.node } }

    pub fn document(&self) -> &'d Document<'d> { self.document }
    pub fn name(&self) -> &str { self.node().name() }

    pub fn set_name(&self, name: &str) {
        self.document.storage.element_set_name(self.node, name)
    }

    pub fn parent(&'d self) -> Option<ParentOfChild<'d>> {
        let connections = self.document.connections.borrow();

        connections.element_parent(self.node).map(|n| {
            match n {
                raw::ElementPOC(n) => ElementPOC(self.document.wrap_element(n)),
            }
        })
    }

    pub fn append_child(&self, child: Element) {
        let connections = self.document.connections.borrow_mut();
        connections.append_element_child(self.node, child.node)
    }

    pub fn children(&'d self) -> Vec<ChildOfElement<'d>> {
        let connections = self.document.connections.borrow();
        // This is safe because we copy of the children, and the
        // children are never deallocated.
        unsafe {
            let raw_children = connections.element_children(self.node);
            raw_children.iter().map(|n| match n {
                &raw::ElementCOE(n) => ElementCOE(self.document.wrap_element(n)),
            }).collect()
        }
    }
}

impl<'d> PartialEq for Element<'d> {
    fn eq(&self, other: &Element<'d>) -> bool {
        self.node == other.node
    }
}

impl<'d> fmt::Show for Element<'d> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let node = unsafe { &* self.node };
        write!(f, "Element {{ name: {}  }}", node.name())
    }
}

#[deriving(PartialEq,Show)]
pub enum ChildOfElement<'d> {
    ElementCOE(Element<'d>)
}

impl<'d> ChildOfElement<'d> {
    pub fn element(self) -> Option<Element<'d>> {
        match self {
            ElementCOE(n) => Some(n),
        }
    }
}

#[deriving(PartialEq,Show)]
pub enum ParentOfChild<'d> {
    ElementPOC(Element<'d>),
}

#[cfg(test)]
mod test {
    use super::super::Package;
    use super::{ElementCOE};
    use super::{ElementPOC};

    #[test]
    fn elements_belong_to_a_document() {
        let package = Package::new();
        let doc = package.as_document();

        let element = doc.create_element("alpha");

        assert_eq!(&doc, element.document());
    }

    #[test]
    fn elements_can_have_element_children() {
        let package = Package::new();
        let doc = package.as_document();

        let alpha = doc.create_element("alpha");
        let beta  = doc.create_element("beta");

        alpha.append_child(beta);

        let children = alpha.children();

        assert_eq!(children[0], ElementCOE(beta));
    }

    #[test]
    fn element_children_are_ordered() {
        let package = Package::new();
        let doc = package.as_document();

        let greek = doc.create_element("greek");
        let alpha = doc.create_element("alpha");
        let omega = doc.create_element("omega");

        greek.append_child(alpha);
        greek.append_child(omega);

        let children = greek.children();

        assert_eq!(children[0], ElementCOE(alpha));
        assert_eq!(children[1], ElementCOE(omega));
    }

    #[test]
    fn element_children_know_their_parent() {
        let package = Package::new();
        let doc = package.as_document();

        let alpha = doc.create_element("alpha");
        let beta  = doc.create_element("beta");

        alpha.append_child(beta);

        assert_eq!(Some(ElementPOC(alpha)), beta.parent());
    }

    #[test]
    fn changing_parent_of_element_removes_element_from_original_parent() {
        let package = Package::new();
        let doc = package.as_document();

        let parent1 = doc.create_element("parent1");
        let parent2 = doc.create_element("parent2");
        let child = doc.create_element("child");

        parent1.append_child(child);
        parent2.append_child(child);

        assert!(parent1.children().is_empty());
        assert_eq!(1, parent2.children().len());
    }

    #[test]
    fn elements_can_be_renamed() {
        let package = Package::new();
        let doc = package.as_document();

        let alpha = doc.create_element("alpha");
        alpha.set_name("beta");
        assert_eq!(alpha.name(), "beta");
    }
}
<|endoftext|>