<commit_before>#![no_std]

extern crate cortex_m;
extern crate stm32f0x2;
extern crate stm32f0_hal;

use stm32f0x2::{
    GPIOB,
    I2C1,
    RCC,
};
use stm32f0_hal::gpio;

fn main() {
    // This example was developed and tested with the STM32F072B Discovery board
    // and the VL53L0X sattelite board. It assumes that the VL53L0X satellite
    // board is connected to the discovery board in the following way:
    // - GND to GND, VDD to 3V.
    // - XSDN_I to VDD, via a 10kOhm pull-up resistor.
    // - SCL_I to PB6, SDA_I to PB7.

    cortex_m::interrupt::free(|cs| {
        let rcc   = RCC.borrow(cs);
        let gpiob = GPIOB.borrow(cs);
        let i2c   = I2C1.borrow(cs);

        // Set up LEDs that we can later use to signal error or success
        //
        // These LEDs are marked as LD3, LD4, and LD5 on the STM32F0 Discovery
        // board. Please note that the board's documentation that matches those
        // names to PC6, PC8, and PC9 is not correct. It also mixes up the
        // colors of the LEDs. At least that's the case with the board I have in
        // front of me.
        let mut led_init    = gpio::Output::setup(gpio::Pin::PC8); // orange
        let mut led_success = gpio::Output::setup(gpio::Pin::PC9); // green
        let mut led_error   = gpio::Output::setup(gpio::Pin::PC6); // red

        led_init.high();
        led_success.low();
        led_error.low();

        // Enable clock for GPIOB
        //
        // I think this is already included in the GPIO output configuration
        // above, but it's more robust to do it again here explicitely, in case
        // that code changes, or this example switches to another method of
        // signalling success or failure.
        rcc.ahbenr.modify(|_, w| w.iopben().enabled());

        // Enable clock for I2C1
        rcc.apb1enr.modify(|_, w| w.i2c1en().enabled());

        // Reset I2C1 peripheral
        rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit());
        rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit());

        // Select alternate I2C functions on pins
        // See data sheet, page 42 and reference manual, section 8.4.9.
        gpiob.afrl.modify(|_, w|
            w
                .afrl6().af1() // I2C1_SCL on PB6
                .afrl7().af1() // I2C1_SDA on PB7
        );

        // Configure the pins
        //
        // I'm basically winging it here. If the need for setting the
        // configuration like this is explained somewhere in the reference
        // manual, I don't know where. The following is based on my own
        // understanding, and bits and pieces I've gathered from around the
        // internet.
        //
        // Fact is, the pins need to be configured (there's no I2C signal
        // otherwise), and the following configuration works.
        gpiob.moder.modify(|_, w|
            w
                .moder6().alternate()
                .moder7().alternate()
        );
        gpiob.ospeedr.modify(|_, w|
            w
                .ospeedr6().low_speed()
                .ospeedr7().low_speed()
        );
        gpiob.otyper.modify(|_, w|
            w
                .ot6().open_drain()
                .ot7().open_drain()
        );

        // Select HSI as the clock source for I2C1
        // This is the default, so unless other code has changed this
        // configuration, the following line is redundant.
        rcc.cfgr3.modify(|_, w| w.i2c1sw().hsi());

        // Make sure the I2C peripheral is disabled
        // The configuration below is not allowed, while I2C is enabled.
        i2c.cr1.modify(|_, w| w.pe().clear_bit());

        // Noise filter configuration would go here, if required. By default, a
        // spec-compliant analog filter is enabled, and I don't see a reason to
        // change that.

        // Configure I2C timings
        // The following values are taken from table 91 on page 650 (section
        // 26.4.10) in the reference manual. This is the right table because the
        // 8 MHz HSI clock has been selected above. Let's choose 100 kHz for the
        // I2C frequency.
        i2c.timingr.modify(|_, w|
            unsafe {
                w
                    .presc().bits(1)
                    .scll().bits(0x13) // required because of master mode
                    .sclh().bits(0xf)  // required because of master mode
                    .sdadel().bits(0x2)
                    .scldel().bits(0x4)
            }
        );

        // Enable I2C peripheral
        i2c.cr1.modify(|_, w| w.pe().set_bit());

        // Configure and start I2C write
        i2c.cr2.write(|w|
            unsafe {
                w
                    // 7-bit addressing mode
                    .add10().clear_bit()
                    // slave address
                    .sadd1().bits(0x52 >> 1)
                    .sadd0().bit(false) // write
                    // write config
                    .rd_wrn().clear_bit() // set transfer direction to write
                    .nbytes().bits(1)     // send 1 byte, the register index
                    .reload().clear_bit() // only send <nbytes> bytes
                    .autoend().set_bit()  // automatically send STOP signal
                    .start().set_bit()    // start signal to start transmission
            }
        );

        // Wait for transmit register to be empty
        while i2c.isr.read().txe().bit_is_clear() {}

        // Send index of reference register
        i2c.txdr.write(|w| w.txdata().bits(0xC0));

        // Wait until transfer is complete
        // Since we set the AUTOEND flag above, the peripheral should
        // automatically generate a stop condition.
        while i2c.isr.read().stopf().bit_is_clear() {}

        // Configure and start I2C read
        i2c.cr2.write(|w|
            unsafe {
                w
                    // 7-bit addressing mode
                    .add10().clear_bit()
                    // slave address
                    .sadd1().bits(0x52 >> 1)
                    .sadd0().bit(true) // read
                    // read config
                    .rd_wrn().set_bit()   // set transfer direction to read
                    .nbytes().bits(1)     // receive 1 byte
                    .reload().clear_bit() // only receive <nbytes> bytes
                    .autoend().set_bit()  // automatically send STOP signal
                    .start().set_bit()    // start signal to start transmission
            }
        );

        // Wait until byte has been received
        while i2c.isr.read().rxne().bit_is_clear() {}

        // Read received byte
        let byte = i2c.rxdr.read().rxdata().bits();

        // Check received data
        // We expect that it's the hardcoded value from the reference register
        // we were reading.
        if byte == 0xEE {
            led_success.high();
        }
        else {
            led_error.high();
        }
    });
}
<commit_msg>Extract I2C code into reusable functions<commit_after>#![no_std]

extern crate cortex_m;
extern crate stm32f0x2;
extern crate stm32f0_hal;

use stm32f0x2::{
    GPIOB,
    I2C1,
    RCC,
};
use stm32f0_hal::gpio;

fn main() {
    // This example was developed and tested with the STM32F072B Discovery board
    // and the VL53L0X sattelite board. It assumes that the VL53L0X satellite
    // board is connected to the discovery board in the following way:
    // - GND to GND, VDD to 3V.
    // - XSDN_I to VDD, via a 10kOhm pull-up resistor.
    // - SCL_I to PB6, SDA_I to PB7.

    cortex_m::interrupt::free(|cs| {
        let rcc   = RCC.borrow(cs);
        let gpiob = GPIOB.borrow(cs);
        let i2c   = I2C1.borrow(cs);

        // Set up LEDs that we can later use to signal error or success
        //
        // These LEDs are marked as LD3, LD4, and LD5 on the STM32F0 Discovery
        // board. Please note that the board's documentation that matches those
        // names to PC6, PC8, and PC9 is not correct. It also mixes up the
        // colors of the LEDs. At least that's the case with the board I have in
        // front of me.
        let mut led_init    = gpio::Output::setup(gpio::Pin::PC8); // orange
        let mut led_success = gpio::Output::setup(gpio::Pin::PC9); // green
        let mut led_error   = gpio::Output::setup(gpio::Pin::PC6); // red

        led_init.high();
        led_success.low();
        led_error.low();

        let vl53l0x_address = 0x52;

        init_i2c(rcc, gpiob, i2c);
        if let Err(_) = write_i2c(vl53l0x_address, &[0xC0], i2c) {
            led_error.high();
            loop {}
        }
        let mut buffer = [0u8; 1];
        if let Err(_) = read_i2c(vl53l0x_address, &mut buffer, i2c) {
            led_error.high();
            loop {}
        }

        // Check received data
        // We expect that it's the hardcoded value from the reference register
        // we were reading.
        if buffer[0] == 0xEE {
            led_success.high();
        }
        else {
            led_error.high();
        }
    });
}

/// Initializes the I2C1 peripheral
///
/// This function has various limitations:
/// - It doesn't check for error conditions.
/// - It is specific to I2C1.
/// - It can only use PB6 for SCL and PB7 for SDA.
/// - It can only use the HSI as the clock source.
/// - The I2C frequency is hard-coded to 100kHz.
///
/// In addition, this function does all its work by accessing the registers
/// directly, which might interfere with other modules that use the same
/// registers.
fn init_i2c(rcc: &RCC, gpiob: &GPIOB, i2c: &I2C1) {
    // Enable clock for GPIOB
    rcc.ahbenr.modify(|_, w| w.iopben().enabled());

    // Enable clock for I2C1
    rcc.apb1enr.modify(|_, w| w.i2c1en().enabled());

    // Reset I2C1 peripheral
    rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit());
    rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit());

    // Select alternate I2C functions on pins
    // See data sheet, page 42 and reference manual, section 8.4.9.
    gpiob.afrl.modify(|_, w|
        w
            .afrl6().af1() // I2C1_SCL on PB6
            .afrl7().af1() // I2C1_SDA on PB7
    );

    // Configure the pins
    //
    // I'm basically winging it here. If the need for setting the
    // configuration like this is explained somewhere in the reference
    // manual, I don't know where. The following is based on my own
    // understanding, and bits and pieces I've gathered from around the
    // internet.
    //
    // Fact is, the pins need to be configured (there's no I2C signal
    // otherwise), and the following configuration works.
    gpiob.moder.modify(|_, w|
        w
            .moder6().alternate()
            .moder7().alternate()
    );
    gpiob.ospeedr.modify(|_, w|
        w
            .ospeedr6().low_speed()
            .ospeedr7().low_speed()
    );
    gpiob.otyper.modify(|_, w|
        w
            .ot6().open_drain()
            .ot7().open_drain()
    );

    // Select HSI as the clock source for I2C1
    // This is the default, so unless other code has changed this
    // configuration, the following line is redundant.
    rcc.cfgr3.modify(|_, w| w.i2c1sw().hsi());

    // Make sure the I2C peripheral is disabled
    // The configuration below is not allowed, while I2C is enabled.
    i2c.cr1.modify(|_, w| w.pe().clear_bit());

    // Noise filter configuration would go here, if required. By default, a
    // spec-compliant analog filter is enabled, and I don't see a reason to
    // change that.

    // Configure I2C timings
    // The following values are taken from table 91 on page 650 (section
    // 26.4.10) in the reference manual. This is the right table because the
    // 8 MHz HSI clock has been selected above. Let's choose 100 kHz for the
    // I2C frequency.
    i2c.timingr.modify(|_, w|
        unsafe {
            w
                .presc().bits(1)
                .scll().bits(0x13) // required because of master mode
                .sclh().bits(0xf)  // required because of master mode
                .sdadel().bits(0x2)
                .scldel().bits(0x4)
        }
    );

    // Enable I2C peripheral
    i2c.cr1.modify(|_, w| w.pe().set_bit());
}

/// Write to the I2C bus
///
/// Writes the data to the I2C bus. Blocks until all data has been written.
///
/// This function has the following limitations:
/// - It is specific to I2C1.
/// - It only supports writing up to 255 bytes at a time.
/// - Writing more than 1 byte should work, but hasn't been tested.
fn write_i2c(address: u8, data: &[u8], i2c: &I2C1) -> Result<(), WriteError> {
    let nbytes = if data.len() <= u8::max_value() as usize {
        data.len() as u8
    }
    else {
        return Err(WriteError::DataTooLong);
    };

    // Configure and start I2C write
    i2c.cr2.write(|w|
        unsafe {
            w
                // 7-bit addressing mode
                .add10().clear_bit()
                // slave address
                .sadd1().bits(address >> 1)
                .sadd0().bit(false) // write
                // write config
                .rd_wrn().clear_bit()  // set transfer direction to write
                .nbytes().bits(nbytes) // set number of bytes to send
                .reload().clear_bit()  // only send <nbytes> bytes
                .autoend().set_bit()   // automatically send STOP signal
                .start().set_bit()     // start transmission
        }
    );

    for &b in data {
        // Wait for transmit register to be empty
        while i2c.isr.read().txe().bit_is_clear() {}

        // Send index of reference register
        i2c.txdr.write(|w| w.txdata().bits(b));
    }

    // Wait until transfer is complete
    // Since we set the AUTOEND flag above, the peripheral should
    // automatically generate a stop condition.
    while i2c.isr.read().stopf().bit_is_clear() {}

    Ok(())
}

/// Read from the I2C bus
///
/// Reads data from the I2C bus until the buffer has been filled. Blocks until
/// all bytes have been read.
///
/// This function has the following limitations:
/// - It is specific to I2C1.
/// - It only supports reading up to 255 bytes at a time.
/// - Reading more than 1 byte should work, but hasn't been tested.
fn read_i2c(address: u8, buffer: &mut [u8], i2c: &I2C1)
    -> Result<(), ReadError>
{
    let nbytes = if buffer.len() <= u8::max_value() as usize {
        buffer.len() as u8
    }
    else {
        return Err(ReadError::BufferTooLong)
    };

    // Configure and start I2C read
    i2c.cr2.write(|w|
        unsafe {
            w
                // 7-bit addressing mode
                .add10().clear_bit()
                // slave address
                .sadd1().bits(address >> 1)
                .sadd0().bit(true) // read
                // read config
                .rd_wrn().set_bit()   // set transfer direction to read
                .nbytes().bits(nbytes)     // receive 1 byte
                .reload().clear_bit() // only receive <nbytes> bytes
                .autoend().set_bit()  // automatically send STOP signal
                .start().set_bit()    // start signal to start transmission
        }
    );

    for b in buffer {
        // Wait until byte has been received
        while i2c.isr.read().rxne().bit_is_clear() {}

        // Read received byte
        *b = i2c.rxdr.read().rxdata().bits();
    }

    Ok(())
}

pub enum WriteError {
    DataTooLong,
}

pub enum ReadError {
    BufferTooLong,
}
<|endoftext|>


<commit_before>#[derive(Debug)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

//for red-black tree
#[derive(Debug)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }
}

impl Tree {
    fn new(v: &i32) -> Tree {
        Tree {
            enter: Node::new(v),
            left: None,
            right: None,
        }
    }

    fn insert(&mut self, v: &i32) {
        let target = if *v > self.enter.val {
            &mut self.right
        } else {
            &mut self.left
        };

        match target {
            Some(next) => next.insert(v),
            None => {
                let new_node = Node::new(v);
                let new_tree = Tree {
                    enter: new_node,
                    left: None,
                    right: None,
                };
                *target = Some(Box::new(new_tree));
            }
        }
    }
}

fn main() {}
<commit_msg>add a bit<commit_after>#[derive(Debug)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

//for red-black tree
#[derive(Debug)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }
}

impl Tree {
    fn new(v: &i32) -> Tree {
        Tree {
            enter: Node::new(v),
            left: None,
            right: None,
        }
    }

    fn insert(&mut self, v: &i32) {
        let target = if *v > self.enter.val {
            &mut self.right
        } else {
            &mut self.left
        };
        //println!("target is -> {:?}", target);
        match target {
            Some(next) => {
                println!("next is -> {:?}", &next);
                next.insert(v)
            }
            None => {
                let new_node = Node::new(v);
                let new_tree = Tree {
                    enter: new_node,
                    left: None,
                    right: None,
                };
                *target = Some(Box::new(new_tree));
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> Result<&mut Self, String> {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }
}

fn main() {
    let mut a = Tree::new(&3);
    a.insert(&2);
    a.insert(&1);

    println!("{:?}", a);
}
<|endoftext|>


<commit_before>use serde_json;
use std::collections::HashMap;

/// Permitted JSON-API values (all JSON Values)
pub type JsonApiValue = serde_json::Value;
/// Vector of Resource
pub type Resources = Vec<Resource>;
/// Vector of ResourceIdentifiers
pub type ResourceIdentifiers = Vec<ResourceIdentifier>;
pub type Links = HashMap<String, JsonApiValue>;
/// Meta-data object, can contain any data
pub type Meta = HashMap<String, JsonApiValue>;
/// Resource Attributes, can be any JSON value
pub type ResourceAttributes = HashMap<String, JsonApiValue>;
/// Map of relationships with other objects
pub type Relationships = HashMap<String, Relationship>;
/// Side-loaded Resources
pub type Included = Vec<Resource>;
/// Data-related errors
pub type JsonApiErrors = Vec<JsonApiError>;

/// Resource Identifier
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ResourceIdentifier {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: String,
}

/// JSON-API Resource
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Resource {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: String,
    pub attributes: ResourceAttributes,
    pub relationships: Option<Relationships>,
    pub links: Option<Links>,
}

/// Relationship with another object
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Relationship {
    pub data: IdentifierData,
    pub links: Option<Links>,
}

/// Valid data Resource (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum PrimaryData {
    None,
    Single(Resource),
    Multiple(Resources),
}

/// Valid Resource Identifier (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum IdentifierData {
    None,
    Single(ResourceIdentifier),
    Multiple(ResourceIdentifiers),
}

/// The specification refers to this as a top-level `document`
/// The spec dictates that the document must have least one of `data`, `errors` or `meta`.
/// Of these, `data` and `errors` must not co-exist.
/// The optional field `included` may only be present if the `data` field is present too.
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiDocument {
    pub data: Option<PrimaryData>,
    pub included: Option<Resources>,
    pub links: Option<Links>,
    pub meta: Option<Meta>,
    pub errors: Option<JsonApiErrors>,
    pub jsonapi: Option<JsonApiInfo>,
}

/// Error location
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ErrorSource {
    pub pointer: Option<String>,
    pub parameter: Option<String>,
}

/// JSON-API Error
/// All fields are optional
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiError {
    pub id: Option<String>,
    pub links: Option<Links>,
    pub status: Option<String>,
    pub code: Option<String>,
    pub title: Option<String>,
    pub detail: Option<String>,
    pub source: Option<ErrorSource>,
    pub meta: Option<Meta>,
}

/// Optional JsonApiDocument payload identifying the JSON-API version the server implements
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiInfo {
    pub version: Option<String>,
    pub meta: Option<Meta>,
}

/// Pagination links
#[derive(Serialize, Deserialize, Debug)]
pub struct Pagination {
    pub first: Option<String>,
    pub prev: Option<String>,
    pub next: Option<String>,
    pub last: Option<String>,
}

impl Pagination {
    pub fn has_first(&self) -> bool {
        !self.first.is_none()
    }
    pub fn has_prev(&self) -> bool {
        !self.prev.is_none()
    }
    pub fn has_next(&self) -> bool {
        !self.next.is_none()
    }
    pub fn has_last(&self) -> bool {
        !self.last.is_none()
    }
}

/// Top-level JSON-API Document
impl JsonApiDocument {
    fn has_errors(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_meta(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_included(&self) -> bool {
        !self.included.is_none()
    }
    fn has_data(&self) -> bool {
        !self.data.is_none()
    }
    /// This function returns `false` if the `JsonApiDocument` contains any violations of the
    /// specification. See `DocumentValidationError`
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors};
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// assert_eq!(doc.is_valid(), false);
    /// ```
    pub fn is_valid(&self) -> bool {
        match self.validate() {
            Some(_) => false,
            None => true,
        }
    }

    /// This function returns a `Vec` with identified specification violations enumerated in
    /// `DocumentValidationError`
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors, DocumentValidationError};
    ///
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// match doc.validate() {
    ///   Some(errors) => {
    ///     assert!(
    ///       errors.contains(
    ///         &DocumentValidationError::DataWithErrors
    ///       )
    ///     )
    ///   }
    ///   None => assert!(false)
    /// }
    /// ```
    pub fn validate(&self) -> Option<Vec<DocumentValidationError>> {

        let mut errors = Vec::<DocumentValidationError>::new();

        if self.has_data() && self.has_errors() {
            errors.push(DocumentValidationError::DataWithErrors);
        }

        if self.has_included() && !self.has_data() {
            errors.push(DocumentValidationError::IncludedWithoutData);
        }

        if !(self.has_data() || self.has_meta() || self.has_errors()) {
            errors.push(DocumentValidationError::MissingContent);
        }

        match errors.len() {
            0 => None,
            _ => Some(errors),
        }

    }

    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::JsonApiDocument;
    ///
    /// let serialized = r#"{
    ///   "data" : [
    ///     { "id":"1", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"2", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"3", "type":"post", "attributes":{}, "relationships":{}, "links" :{} }
    ///   ]
    /// }"#;
    /// let doc = JsonApiDocument::from_str(&serialized);
    /// assert_eq!(doc.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        let data: Result<Self, serde_json::Error> = serde_json::from_str(&s);
        data
    }
}

/// Top-level (Document) JSON-API specification violations
#[derive(Debug, PartialEq)]
pub enum DocumentValidationError {
    IncludedWithoutData,
    DataWithErrors,
    MissingContent,
}
<commit_msg>docs: Minor doc repositioning<commit_after>use serde_json;
use std::collections::HashMap;

/// Permitted JSON-API values (all JSON Values)
pub type JsonApiValue = serde_json::Value;
/// Vector of Resource
pub type Resources = Vec<Resource>;
/// Vector of ResourceIdentifiers
pub type ResourceIdentifiers = Vec<ResourceIdentifier>;
pub type Links = HashMap<String, JsonApiValue>;
/// Meta-data object, can contain any data
pub type Meta = HashMap<String, JsonApiValue>;
/// Resource Attributes, can be any JSON value
pub type ResourceAttributes = HashMap<String, JsonApiValue>;
/// Map of relationships with other objects
pub type Relationships = HashMap<String, Relationship>;
/// Side-loaded Resources
pub type Included = Vec<Resource>;
/// Data-related errors
pub type JsonApiErrors = Vec<JsonApiError>;

/// Resource Identifier
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ResourceIdentifier {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: String,
}

/// JSON-API Resource
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Resource {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: String,
    pub attributes: ResourceAttributes,
    pub relationships: Option<Relationships>,
    pub links: Option<Links>,
}

/// Relationship with another object
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Relationship {
    pub data: IdentifierData,
    pub links: Option<Links>,
}

/// Valid data Resource (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum PrimaryData {
    None,
    Single(Resource),
    Multiple(Resources),
}

/// Valid Resource Identifier (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum IdentifierData {
    None,
    Single(ResourceIdentifier),
    Multiple(ResourceIdentifiers),
}

/// The specification refers to this as a top-level `document`
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiDocument {
    pub data: Option<PrimaryData>,
    pub included: Option<Resources>,
    pub links: Option<Links>,
    pub meta: Option<Meta>,
    pub errors: Option<JsonApiErrors>,
    pub jsonapi: Option<JsonApiInfo>,
}

/// Error location
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ErrorSource {
    pub pointer: Option<String>,
    pub parameter: Option<String>,
}

/// JSON-API Error
/// All fields are optional
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiError {
    pub id: Option<String>,
    pub links: Option<Links>,
    pub status: Option<String>,
    pub code: Option<String>,
    pub title: Option<String>,
    pub detail: Option<String>,
    pub source: Option<ErrorSource>,
    pub meta: Option<Meta>,
}

/// Optional JsonApiDocument payload identifying the JSON-API version the server implements
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiInfo {
    pub version: Option<String>,
    pub meta: Option<Meta>,
}

/// Pagination links
#[derive(Serialize, Deserialize, Debug)]
pub struct Pagination {
    pub first: Option<String>,
    pub prev: Option<String>,
    pub next: Option<String>,
    pub last: Option<String>,
}

impl Pagination {
    pub fn has_first(&self) -> bool {
        !self.first.is_none()
    }
    pub fn has_prev(&self) -> bool {
        !self.prev.is_none()
    }
    pub fn has_next(&self) -> bool {
        !self.next.is_none()
    }
    pub fn has_last(&self) -> bool {
        !self.last.is_none()
    }
}

/// Top-level JSON-API Document
impl JsonApiDocument {
    fn has_errors(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_meta(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_included(&self) -> bool {
        !self.included.is_none()
    }
    fn has_data(&self) -> bool {
        !self.data.is_none()
    }
    /// This function returns `false` if the `JsonApiDocument` contains any violations of the
    /// specification. See `DocumentValidationError`
    ///
    /// The spec dictates that the document must have least one of `data`, `errors` or `meta`.
    /// Of these, `data` and `errors` must not co-exist.
    /// The optional field `included` may only be present if the `data` field is present too.
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors};
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// assert_eq!(doc.is_valid(), false);
    /// ```
    pub fn is_valid(&self) -> bool {
        match self.validate() {
            Some(_) => false,
            None => true,
        }
    }

    /// This function returns a `Vec` with identified specification violations enumerated in
    /// `DocumentValidationError`
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors, DocumentValidationError};
    ///
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// match doc.validate() {
    ///   Some(errors) => {
    ///     assert!(
    ///       errors.contains(
    ///         &DocumentValidationError::DataWithErrors
    ///       )
    ///     )
    ///   }
    ///   None => assert!(false)
    /// }
    /// ```
    pub fn validate(&self) -> Option<Vec<DocumentValidationError>> {

        let mut errors = Vec::<DocumentValidationError>::new();

        if self.has_data() && self.has_errors() {
            errors.push(DocumentValidationError::DataWithErrors);
        }

        if self.has_included() && !self.has_data() {
            errors.push(DocumentValidationError::IncludedWithoutData);
        }

        if !(self.has_data() || self.has_meta() || self.has_errors()) {
            errors.push(DocumentValidationError::MissingContent);
        }

        match errors.len() {
            0 => None,
            _ => Some(errors),
        }

    }

    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::JsonApiDocument;
    ///
    /// let serialized = r#"{
    ///   "data" : [
    ///     { "id":"1", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"2", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"3", "type":"post", "attributes":{}, "relationships":{}, "links" :{} }
    ///   ]
    /// }"#;
    /// let doc = JsonApiDocument::from_str(&serialized);
    /// assert_eq!(doc.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        let data: Result<Self, serde_json::Error> = serde_json::from_str(&s);
        data
    }
}

/// Top-level (Document) JSON-API specification violations
#[derive(Debug, PartialEq)]
pub enum DocumentValidationError {
    IncludedWithoutData,
    DataWithErrors,
    MissingContent,
}
<|endoftext|>


<commit_before>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(value)
    }
}

fn check_call_ret(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

fn get_keyring(id: KeyringSerial, create: bool) -> Result<Keyring> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, Keyring { id: res, })
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, false)
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, true)
    }

    pub fn join_anonymous_session() -> Result<Self> {
        let res = unsafe { keyctl_join_session_keyring(ptr::null()) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn join_session(name: &str) -> Result<Self> {
        let nameptr = CString::new(name).unwrap().as_ptr();
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn search(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, self.id) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        // TODO: turn bytestream into vec of keys
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn find_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { find_key_by_type_and_desc(typeptr, descptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, ptr::null(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key_with_fallback(&mut self, type_: &str, description: &str, info: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let infoptr = CString::new(info).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, infoptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }
}

pub struct Key {
    id: KeyringSerial,
}

extern fn unlink_cb(
    parent:     key_serial_t,
    key:        key_serial_t,
    desc:       *mut libc::c_char,
    desc_len:   libc::c_int,
    data:       *mut libc::c_void)
    -> libc::c_int {
    unimplemented!()
}

impl Key {
    pub fn request(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key(type_, description)
    }

    pub fn request_with_fallback(type_: &str, description: &str, info: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key_with_fallback(type_, description, info)
    }

    pub fn find(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.find_key(type_, description)
    }

    pub fn search(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.search(type_, description)
    }

    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring(self.id, false)
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn unlink(self, keyring: &Keyring) -> Result<()> {
        check_call(unsafe { keyctl_unlink(self.id, keyring.id) }, ())
    }

    pub fn unlink_from_all(self, keyring: &mut Keyring) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_key_scan(keyring.id, unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn unlink_from_session(self) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_session_key_scan(unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, -1) }, ())
    }

    pub fn chgrp(&mut self, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, -1, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<KeyDescription> {
        self.description_raw().map(|desc| {
            KeyDescription::parse(desc)
        })
    }

    fn description_raw(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }

    pub fn manage(&mut self) -> Result<KeyManager> {
        check_call(unsafe { keyctl_assume_authority(self.id) }, KeyManager {
            key: Key {
                id: self.id,
            },
        })
    }
}

pub struct KeyDescription {
    pub type_:          String,
    pub uid:            uid_t,
    pub gid:            gid_t,
    pub perms:          KeyPermissions,
    pub description:    String,
}

impl KeyDescription {
    fn parse(desc: String) -> KeyDescription {
        unimplemented!()
    }
}

pub struct KeyManager {
    key: Key,
}

impl KeyManager {
    pub fn instantiate(self, keyring: &Keyring, payload: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_instantiate(self.key.id, payload.as_ptr() as *const libc::c_void, payload.len(), keyring.id) }, ())
    }

    pub fn reject(self, keyring: &Keyring, timeout: u32, error: errno::Errno) -> Result<()> {
        let errno::Errno(errval) = error;
        check_call(unsafe { keyctl_reject(self.key.id, timeout, errval as u32, keyring.id) }, ())
    }

    pub fn negate(self, keyring: &Keyring, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_negate(self.key.id, timeout, keyring.id) }, ())
    }
}
<commit_msg>api: set the length of the buffer<commit_after>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(value)
    }
}

fn check_call_ret(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

fn get_keyring(id: KeyringSerial, create: bool) -> Result<Keyring> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, Keyring { id: res, })
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, false)
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, true)
    }

    pub fn join_anonymous_session() -> Result<Self> {
        let res = unsafe { keyctl_join_session_keyring(ptr::null()) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn join_session(name: &str) -> Result<Self> {
        let nameptr = CString::new(name).unwrap().as_ptr();
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn search(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, self.id) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        // TODO: turn bytestream into vec of keys
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn find_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { find_key_by_type_and_desc(typeptr, descptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, ptr::null(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key_with_fallback(&mut self, type_: &str, description: &str, info: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let infoptr = CString::new(info).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, infoptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }
}

pub struct Key {
    id: KeyringSerial,
}

extern fn unlink_cb(
    parent:     key_serial_t,
    key:        key_serial_t,
    desc:       *mut libc::c_char,
    desc_len:   libc::c_int,
    data:       *mut libc::c_void)
    -> libc::c_int {
    unimplemented!()
}

impl Key {
    pub fn request(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key(type_, description)
    }

    pub fn request_with_fallback(type_: &str, description: &str, info: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key_with_fallback(type_, description, info)
    }

    pub fn find(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.find_key(type_, description)
    }

    pub fn search(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.search(type_, description)
    }

    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring(self.id, false)
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn unlink(self, keyring: &Keyring) -> Result<()> {
        check_call(unsafe { keyctl_unlink(self.id, keyring.id) }, ())
    }

    pub fn unlink_from_all(self, keyring: &mut Keyring) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_key_scan(keyring.id, unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn unlink_from_session(self) -> usize {
        let mut id_copy = self.id;
        let data: *mut KeyringSerial = &mut id_copy;
        let ret = unsafe { recursive_session_key_scan(unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, -1) }, ())
    }

    pub fn chgrp(&mut self, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, -1, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<KeyDescription> {
        self.description_raw().map(|desc| {
            KeyDescription::parse(desc)
        })
    }

    fn description_raw(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        let actual_sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        unsafe { buffer.set_len(actual_sz as usize) };
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }

    pub fn manage(&mut self) -> Result<KeyManager> {
        check_call(unsafe { keyctl_assume_authority(self.id) }, KeyManager {
            key: Key {
                id: self.id,
            },
        })
    }
}

pub struct KeyDescription {
    pub type_:          String,
    pub uid:            uid_t,
    pub gid:            gid_t,
    pub perms:          KeyPermissions,
    pub description:    String,
}

impl KeyDescription {
    fn parse(desc: String) -> KeyDescription {
        unimplemented!()
    }
}

pub struct KeyManager {
    key: Key,
}

impl KeyManager {
    pub fn instantiate(self, keyring: &Keyring, payload: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_instantiate(self.key.id, payload.as_ptr() as *const libc::c_void, payload.len(), keyring.id) }, ())
    }

    pub fn reject(self, keyring: &Keyring, timeout: u32, error: errno::Errno) -> Result<()> {
        let errno::Errno(errval) = error;
        check_call(unsafe { keyctl_reject(self.key.id, timeout, errval as u32, keyring.id) }, ())
    }

    pub fn negate(self, keyring: &Keyring, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_negate(self.key.id, timeout, keyring.id) }, ())
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, WriteBytesExt};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, DisplayListId, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {StackingContext, StackingContextId, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>,
               payload_sender: IpcBytesSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Creates an `ImageKey`.
    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    /// Adds an image and returns the corresponding `ImageKey`.
    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Updates a specific image.
    ///
    /// Currently doesn't support changing dimensions or format by updating.
    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    /// Deletes the specific image.
    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    /// Sets the root pipeline.
    ///
    /// # Examples
    ///
    /// ```
    /// let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
    /// let api = sender.create_api();
    /// ...
    /// let pipeline_id = PipelineId(0,0);
    /// api.set_root_pipeline(pipeline_id);
    /// ```
    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Non-blocking, it notifies a worker process which processes the stacking context.
    /// When it's done and a RenderNotifier has been set in `webrender::renderer::Renderer`,
    /// [new_frame_ready()][notifier] gets called.
    ///
    /// Note: Scrolling doesn't require an own Frame.
    ///
    /// Arguments:
    ///
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: The unique Frame ID, monotonically increasing.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    ///
    /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(stacking_context_id.0).unwrap();
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            payload.extend_from_slice(built_display_list.data());
        }
        payload.extend_from_slice(auxiliary_lists.data());

        self.payload_sender.send(&payload[..]).unwrap();
    }

    /// Scrolls the scrolling layer under the `cursor`
    ///
    /// Webrender looks for the layer closest to the user
    /// which has `ScrollPolicy::Scrollable` set.
    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    /// Translates a point from viewport coordinates to layer space
    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}
<commit_msg>Re-adding newline<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, WriteBytesExt};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, DisplayListId, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {StackingContext, StackingContextId, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>,
               payload_sender: IpcBytesSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Creates an `ImageKey`.
    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    /// Adds an image and returns the corresponding `ImageKey`.
    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Updates a specific image.
    ///
    /// Currently doesn't support changing dimensions or format by updating.
    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    /// Deletes the specific image.
    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    /// Sets the root pipeline.
    ///
    /// # Examples
    ///
    /// ```
    /// let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
    /// let api = sender.create_api();
    /// ...
    /// let pipeline_id = PipelineId(0,0);
    /// api.set_root_pipeline(pipeline_id);
    /// ```
    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Non-blocking, it notifies a worker process which processes the stacking context.
    /// When it's done and a RenderNotifier has been set in `webrender::renderer::Renderer`,
    /// [new_frame_ready()][notifier] gets called.
    ///
    /// Note: Scrolling doesn't require an own Frame.
    ///
    /// Arguments:
    ///
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: The unique Frame ID, monotonically increasing.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    ///
    /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(stacking_context_id.0).unwrap();
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            payload.extend_from_slice(built_display_list.data());
        }
        payload.extend_from_slice(auxiliary_lists.data());

        self.payload_sender.send(&payload[..]).unwrap();
    }

    /// Scrolls the scrolling layer under the `cursor`
    ///
    /// Webrender looks for the layer closest to the user
    /// which has `ScrollPolicy::Scrollable` set.
    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    /// Translates a point from viewport coordinates to layer space
    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}

<|endoftext|>