<commit_before>//! Traits for interpreting font data

use font_types::Tag;

use crate::font_data::FontData;

/// A type that can be parsed from raw table data.
pub trait FontRead<'a>: Sized {
    fn read(data: FontData<'a>) -> Result<Self, ReadError>;
}

//NOTE: this is separate so that it can be a super trait of FontReadWithArgs and
//ComputeSize, without them needing to know about each other? I'm not sure this
//is necessary, but I don't know the full heirarchy of traits I'm going to need
//yet, so this seems... okay?

/// A trait for a type that needs additional arguments to be read.
pub trait ReadArgs {
    type Args: Copy;
}

/// A trait for types that require external data in order to be constructed.
pub trait FontReadWithArgs<'a>: Sized + ReadArgs {
    /// read an item, using the provided args.
    ///
    /// If successful, returns a new item of this type, and the number of bytes
    /// used to construct it.
    ///
    /// If a type requires multiple arguments, they will be passed as a tuple.
    //TODO: split up the 'takes args' and 'reports size' parts of this into
    // separate traits
    fn read_with_args(data: FontData<'a>, args: &Self::Args) -> Result<Self, ReadError>;
}

/// A trait for tables that have multiple possible formats.
pub trait Format<T> {
    /// The format value for this table.
    const FORMAT: T;
}

/// A type that can compute its size at runtime, based on some input.
pub trait ComputeSize: ReadArgs {
    /// Compute the number of bytes required to represent this type.
    fn compute_size(args: &Self::Args) -> usize;
}

/// An error that occurs when reading font data
#[derive(Debug, Clone)]
pub enum ReadError {
    OutOfBounds,
    // i64 is flexible enough to store any value we might encounter
    InvalidFormat(i64),
    InvalidSfnt(u32),
    InvalidArrayLen,
    ValidationError,
    NullOffset,
    TableIsMissing(Tag),
    MalformedData(&'static str),
}

impl std::fmt::Display for ReadError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            ReadError::OutOfBounds => write!(f, "An offset was out of bounds"),
            ReadError::InvalidFormat(x) => write!(f, "Invalid format '{x}'"),
            ReadError::InvalidSfnt(ver) => write!(f, "Invalid sfnt version 0x{ver:08X}"),
            ReadError::InvalidArrayLen => {
                write!(f, "Specified array length not a multiple of item size")
            }
            ReadError::ValidationError => write!(f, "A validation error occured"),
            ReadError::NullOffset => write!(f, "An offset was unexpectedly null"),
            ReadError::TableIsMissing(tag) => write!(f, "the {tag} table is missing"),
            ReadError::MalformedData(msg) => write!(f, "Malformed data: '{msg}'"),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ReadError {}
<commit_msg>Update docs for FontRead trait<commit_after>//! Traits for interpreting font data

use font_types::Tag;

use crate::font_data::FontData;

/// A type that can be read from raw table data.
///
/// This trait is implemented for all font tables that are self-describing: that
/// is, tables that do not require any external state in order to interpret their
/// underlying bytes. (Tables that require external state implement
/// [`FontReadWithArgs`] instead)
pub trait FontRead<'a>: Sized {
    /// Read an instace of `Self` from the provided data, performing validation.
    ///
    /// In the case of a table, this method is responsible for ensuring the input
    /// data is consistent: this means ensuring that any versioned fields are
    /// present as required by the version, and that any array lengths are not
    /// out-of-bounds.
    fn read(data: FontData<'a>) -> Result<Self, ReadError>;
}

//NOTE: this is separate so that it can be a super trait of FontReadWithArgs and
//ComputeSize, without them needing to know about each other? I'm not sure this
//is necessary, but I don't know the full heirarchy of traits I'm going to need
//yet, so this seems... okay?

/// A trait for a type that needs additional arguments to be read.
pub trait ReadArgs {
    type Args: Copy;
}

/// A trait for types that require external data in order to be constructed.
pub trait FontReadWithArgs<'a>: Sized + ReadArgs {
    /// read an item, using the provided args.
    ///
    /// If successful, returns a new item of this type, and the number of bytes
    /// used to construct it.
    ///
    /// If a type requires multiple arguments, they will be passed as a tuple.
    //TODO: split up the 'takes args' and 'reports size' parts of this into
    // separate traits
    fn read_with_args(data: FontData<'a>, args: &Self::Args) -> Result<Self, ReadError>;
}

/// A trait for tables that have multiple possible formats.
pub trait Format<T> {
    /// The format value for this table.
    const FORMAT: T;
}

/// A type that can compute its size at runtime, based on some input.
pub trait ComputeSize: ReadArgs {
    /// Compute the number of bytes required to represent this type.
    fn compute_size(args: &Self::Args) -> usize;
}

/// An error that occurs when reading font data
#[derive(Debug, Clone)]
pub enum ReadError {
    OutOfBounds,
    // i64 is flexible enough to store any value we might encounter
    InvalidFormat(i64),
    InvalidSfnt(u32),
    InvalidArrayLen,
    ValidationError,
    NullOffset,
    TableIsMissing(Tag),
    MalformedData(&'static str),
}

impl std::fmt::Display for ReadError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            ReadError::OutOfBounds => write!(f, "An offset was out of bounds"),
            ReadError::InvalidFormat(x) => write!(f, "Invalid format '{x}'"),
            ReadError::InvalidSfnt(ver) => write!(f, "Invalid sfnt version 0x{ver:08X}"),
            ReadError::InvalidArrayLen => {
                write!(f, "Specified array length not a multiple of item size")
            }
            ReadError::ValidationError => write!(f, "A validation error occured"),
            ReadError::NullOffset => write!(f, "An offset was unexpectedly null"),
            ReadError::TableIsMissing(tag) => write!(f, "the {tag} table is missing"),
            ReadError::MalformedData(msg) => write!(f, "Malformed data: '{msg}'"),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ReadError {}
<|endoftext|>


<commit_before>#![feature(platform_intrinsics)]
#![feature(simd, simd_ffi, link_llvm_intrinsics)]
#![feature(cfg_target_feature)]

extern crate rand;
extern crate x86intrin;

pub mod color;
pub mod decision;
pub mod field;
mod field_bit;
#[cfg(target_feature = "avx2")]
mod field_bit_256;
pub mod field_checker;
pub mod frame;
pub mod kumipuyo;
pub mod position;
pub mod rensa_result;
pub mod rensa_tracker;
pub mod score;
pub mod sseext;
<commit_msg>:green_heart: Build rensa_tracker only with AVX2<commit_after>#![feature(platform_intrinsics)]
#![feature(simd, simd_ffi, link_llvm_intrinsics)]
#![feature(cfg_target_feature)]

extern crate rand;
extern crate x86intrin;

pub mod color;
pub mod decision;
pub mod field;
mod field_bit;
#[cfg(all(target_feature = "avx2", target_feature="bmi2"))]
mod field_bit_256;
pub mod field_checker;
pub mod frame;
pub mod kumipuyo;
pub mod position;
pub mod rensa_result;
#[cfg(all(target_feature = "avx2", target_feature="bmi2"))]
pub mod rensa_tracker;
pub mod score;
pub mod sseext;
<|endoftext|>


<commit_before>// Copyright (c) 2018 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

use logging::*;

#[no_mangle]
pub extern "C" fn sys_message()
{
	println!("Hello World form eduOS-rs!");
}
<commit_msg>remove compiler warnings<commit_after>// Copyright (c) 2018 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#[no_mangle]
pub extern "C" fn sys_message()
{
	println!("Hello World form eduOS-rs!");
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};
use tensor::Tensor;
use traits::TensorTrait;

// Vector indexing
impl<'b, T: TensorTrait> Index<&'b [usize]> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, ii: &'b [usize]) -> &'a T {
        assert!(self.canonical);
        let index = self.ravel_index(ii);
        &self.data[index]
    }
}

impl<'b, T: TensorTrait> IndexMut<&'b [usize]> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, ii: &'b [usize]) -> &'a mut T {
        assert!(self.canonical);
        let index = self.ravel_index(ii);
        &mut self.slice_mut()[index]
    }
}

impl<'b, T: TensorTrait> Index<&'b Vec<usize>> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, ii: &'b Vec<usize>) -> &'a T {
        assert!(self.canonical);
        let index = self.ravel_index(&ii[..]);
        &self.data[index]
    }
}

impl<'b, T: TensorTrait> IndexMut<&'b Vec<usize>> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, ii: &'b Vec<usize>) -> &'a mut T {
        assert!(self.canonical);
        //self.canonize_inplace();
        let index = self.ravel_index(&ii[..]);
        &mut self.slice_mut()[index]
    }
}

/*
// Flattened indexing (this will index it as one-dimensional)
impl<T: TensorTrait> Index<usize> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: usize) -> &'a T {
        &self.data[self.mem_offset + _index]
    }
}

impl<T: TensorTrait> IndexMut<usize> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut T {
        //self.harden_inplace();
        let offset = self.mem_offset;
        &mut self.slice_mut()[offset + _index]
    }
}
*/

// 1-D indexing
impl<T: TensorTrait> Index<(usize,)> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: (usize,)) -> &'a T {
        assert!(self.ndim() == 1);
        &self.data[(self.mem_offset as isize + _index.0 as isize * self.strides[0]) as usize]
    }
}

impl<T: TensorTrait> IndexMut<(usize,)> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: (usize,)) -> &'a mut T {
        assert!(self.ndim() == 1);
        let offset = self.mem_offset as isize;
        let s0 = self.strides[0];
        &mut self.slice_mut()[(offset + _index.0 as isize * s0) as usize]
    }
}

// 2-D indexing
impl<T: TensorTrait> Index<(usize, usize)> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: (usize, usize)) -> &'a T {
        assert!(self.ndim() == 2);
        &self.data[self.mem_offset + (_index.0 as isize * self.strides[0] +
                                      _index.1 as isize * self.strides[1]) as usize]
    }
}
impl<T: TensorTrait> IndexMut<(usize, usize)> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: (usize, usize)) -> &'a mut T {
        assert!(self.ndim() == 2);
        let i = self.mem_offset + (_index.0 as isize * self.strides[0] +
                                   _index.1 as isize * self.strides[1]) as usize;
        &mut self.slice_mut()[i]
    }
}

// 3-D indexing
impl<T: TensorTrait> Index<(usize, usize, usize)> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: (usize, usize, usize)) -> &'a T {
        assert!(self.ndim() == 3);
        &self.data[(self.mem_offset as isize +
                    _index.0 as isize * self.strides[0] +
                    _index.1 as isize * self.strides[1] +
                    _index.2 as isize * self.strides[2]) as usize]
    }
}

impl<T: TensorTrait> IndexMut<(usize, usize, usize)> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: (usize, usize, usize)) -> &'a mut T {
        assert!(self.ndim() == 3);
        let offset = self.mem_offset as isize;
        let (s0, s1, s2) = (self.strides[1], self.strides[2], self.strides[3]);
        &mut self.slice_mut()[(offset +
                               _index.0 as isize * s0 +
                               _index.1 as isize * s1 +
                               _index.2 as isize * s2) as usize]
    }
}

<commit_msg>Tweaks to simple indexing<commit_after>use std::ops::{Index, IndexMut};
use tensor::Tensor;
use traits::TensorTrait;

// Vector indexing
impl<'b, T: TensorTrait> Index<&'b [usize]> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, ii: &'b [usize]) -> &'a T {
        assert!(self.canonical);
        let index = self.ravel_index(ii);
        &self.data[index]
    }
}

impl<'b, T: Copy> IndexMut<&'b [usize]> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, ii: &'b [usize]) -> &'a mut T {
        assert!(self.canonical);
        let index = self.ravel_index(ii);
        &mut self.mem_slice_mut()[index]
    }
}

impl<'b, T: Copy> Index<&'b Vec<usize>> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, ii: &'b Vec<usize>) -> &'a T {
        assert!(self.canonical);
        let index = self.ravel_index(&ii[..]);
        &self.data[index]
    }
}

impl<'b, T: TensorTrait> IndexMut<&'b Vec<usize>> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, ii: &'b Vec<usize>) -> &'a mut T {
        assert!(self.canonical);
        //self.canonize_inplace();
        let index = self.ravel_index(&ii[..]);
        &mut self.mem_slice_mut()[index]
    }
}

/*
// Flattened indexing (this will index it as one-dimensional)
impl<T: TensorTrait> Index<usize> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: usize) -> &'a T {
        &self.data[self.mem_offset + _index]
    }
}

impl<T: TensorTrait> IndexMut<usize> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut T {
        //self.harden_inplace();
        let offset = self.mem_offset;
        &mut self.slice_mut()[offset + _index]
    }
}
*/

// 1-D indexing
impl<T: TensorTrait> Index<(usize,)> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: (usize,)) -> &'a T {
        assert!(self.ndim() == 1);
        &self.data[(self.mem_offset as isize + _index.0 as isize * self.strides[0]) as usize]
    }
}

impl<T: TensorTrait> IndexMut<(usize,)> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: (usize,)) -> &'a mut T {
        assert!(self.ndim() == 1);
        let offset = self.mem_offset as isize;
        let s0 = self.strides[0];
        &mut self.mem_slice_mut()[(offset + _index.0 as isize * s0) as usize]
    }
}

// 2-D indexing
impl<T: TensorTrait> Index<(usize, usize)> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: (usize, usize)) -> &'a T {
        assert!(self.ndim() == 2);
        &self.data[self.mem_offset + (_index.0 as isize * self.strides[0] +
                                      _index.1 as isize * self.strides[1]) as usize]
    }
}
impl<T: TensorTrait> IndexMut<(usize, usize)> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: (usize, usize)) -> &'a mut T {
        assert!(self.ndim() == 2);
        let i = self.mem_offset + (_index.0 as isize * self.strides[0] +
                                   _index.1 as isize * self.strides[1]) as usize;
        &mut self.mem_slice_mut()[i]
    }
}

// 3-D indexing
impl<T: TensorTrait> Index<(usize, usize, usize)> for Tensor<T> {
    type Output = T;
    fn index<'a>(&'a self, _index: (usize, usize, usize)) -> &'a T {
        assert!(self.ndim() == 3);
        &self.data[(self.mem_offset as isize +
                    _index.0 as isize * self.strides[0] +
                    _index.1 as isize * self.strides[1] +
                    _index.2 as isize * self.strides[2]) as usize]
    }
}

impl<T: TensorTrait> IndexMut<(usize, usize, usize)> for Tensor<T> {
    fn index_mut<'a>(&'a mut self, _index: (usize, usize, usize)) -> &'a mut T {
        assert!(self.ndim() == 3);
        let offset = self.mem_offset as isize;
        let (s0, s1, s2) = (self.strides[1], self.strides[2], self.strides[3]);
        &mut self.mem_slice_mut()[(offset +
                               _index.0 as isize * s0 +
                               _index.1 as isize * s1 +
                               _index.2 as isize * s2) as usize]
    }
}

<|endoftext|>


<commit_before>use super::{Document,Root,RootChild,Element,ElementChild};

struct Parser;

struct ParsedElement<'a> {
    name: &'a str,
    attributes: Vec<ParsedAttribute<'a>>,
    children: Vec<ParsedElement<'a>>,
}

struct ParsedAttribute<'a> {
    name: &'a str,
    value: &'a str,
}

macro_rules! try_parse(
    ($e:expr) => ({
        match $e {
            None => return None,
            Some(x) => x,
        }
    })
)

// Pattern: 0-or-1
macro_rules! optional_parse(
    ($f:expr, $start:expr) => ({
        match $f {
            None => (None, $start),
            Some((value, next)) => (Some(value), next),
        }
    })
)

impl Parser {
    fn new() -> Parser {
        Parser
    }

    fn parse_preamble<'a>(&self, xml: &'a str) -> &'a str {
        // Parse the preamble
        let idx = xml.find_str("?>").expect("No preamble end");
        let end_of_preamble = idx + "?>".len();
        xml.slice_from(end_of_preamble)
    }

    fn optional_space<'a>(&self, xml: &'a str) -> &'a str {
        match xml.slice_space() {
            Some((_, next_xml)) => next_xml,
            None => xml,
        }
    }

    fn parse_attribute_value_quote<'a>(&self, xml: &'a str, quote: &str) -> Option<(&'a str, &'a str)> {
        let (_, xml) = match xml.slice_literal(quote) {
            None => return None,
            Some(x) => x,
        };
        // TODO: don't consume & or <
        let (value, xml) = xml.slice_until(quote).expect("No value");
        let (_, xml) = xml.slice_literal(quote).expect("No quote");

        Some((value, xml))
    }

    fn parse_attribute<'a>(&self, xml: &'a str) -> Option<(ParsedAttribute<'a>, &'a str)> {
        let (name, xml) = match xml.slice_name() {
            Some(x) => x,
            None => return None,
        };

        let xml = self.optional_space(xml);
        let (_, xml) = xml.slice_literal("=").expect("No equal sign");
        let xml = self.optional_space(xml);

        // Pattern: alternate
        let (value, xml) = match self.parse_attribute_value_quote(xml, "'") {
            Some(x) => x,
            None => match self.parse_attribute_value_quote(xml, "\"") {
                Some(x) => x,
                None => fail!("No attribute value"),
            },
        };

        Some((ParsedAttribute{name: name, value: value}, xml))
    }

    fn parse_attributes<'a>(&self, xml: &'a str) -> (Vec<ParsedAttribute<'a>>, &'a str) {
        let mut xml = xml;
        let mut attrs = Vec::new();

        // Pattern: zero-or-more
        // On failure, return the end of the last successful parse
        loop {
            let (_, after_space) = match xml.slice_space() {
                None => return (attrs, xml),
                Some(x) => x,
            };

            xml = match self.parse_attribute(after_space) {
                None => return (attrs, xml),
                Some((attr, after_attr)) => {
                    attrs.push(attr);
                    after_attr
                },
            };
        }
    }

    fn parse_empty_element<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        let (_, xml) = try_parse!(xml.slice_literal("<"));
        let (name, xml) = try_parse!(xml.slice_name());
        let (attrs, xml) = self.parse_attributes(xml);
        let xml = self.optional_space(xml);
        let (_, xml) = try_parse!(xml.slice_literal("/>"));

        Some((ParsedElement{name: name, attributes: attrs, children: Vec::new()}, xml))
    }

    fn parse_element_start<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        let (_, xml) = try_parse!(xml.slice_literal("<"));
        let (name, xml) = try_parse!(xml.slice_name());
        let (attrs, xml) = self.parse_attributes(xml);
        let xml = self.optional_space(xml);
        let (_, xml) = try_parse!(xml.slice_literal(">"));

        Some((ParsedElement{name: name, attributes: attrs, children: Vec::new()}, xml))
    }

    fn parse_element_end<'a>(&self, xml: &'a str) -> Option<(&'a str, &'a str)> {
        let (_, xml) = try_parse!(xml.slice_literal("</"));
        let (name, xml) = try_parse!(xml.slice_name());
        let xml = self.optional_space(xml);
        let (_, xml) = try_parse!(xml.slice_literal(">"));
        Some((name, xml))
    }

    fn parse_non_empty_element<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        let (mut element, xml) = try_parse!(self.parse_element_start(xml));
        let (child, xml) = optional_parse!(self.parse_element(xml), xml);
        let (name, xml) = try_parse!(self.parse_element_end(xml));

        if element.name != name {
            fail!("tags do not match!");
        }

        child.map(|c| element.children.push(c));

        Some((element, xml))
    }

    fn parse_element<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        // Pattern: alternate
        match self.parse_empty_element(xml) {
            Some(x) => Some(x),
            None => match self.parse_non_empty_element(xml) {
                Some(x) => Some(x),
                None => None,
            },
        }
    }

    fn hydrate_parsed_data(&self, element_data: ParsedElement) -> Document {
        let doc = Document::new();

        let element = doc.new_element(element_data.name.to_string());
        for attr in element_data.attributes.iter() {
            element.set_attribute(attr.name.to_string(), attr.value.to_string());
        }
        for child in element_data.children.iter() {
            let c = doc.new_element(child.name.to_string());//attrs; recursive
            element.append_child(c);
        }
        doc.root().append_child(element);

        doc
    }

    fn parse(&self, xml: &str) -> Document {
        let after_preamble = self.parse_preamble(xml);

        let (element, _tail) = self.parse_element(after_preamble).expect("no element");

        self.hydrate_parsed_data(element)
    }
}

trait XmlStr<'a> {
    fn slice_at(&self, position: uint) -> (&'a str, &'a str);
    fn slice_until(&self, s: &str) -> Option<(&'a str, &'a str)>;
    fn slice_literal(&self, expected: &str) -> Option<(&'a str, &'a str)>;
    fn slice_start_rest(&self, is_first: |char| -> bool, is_rest: |char| -> bool) -> Option<(&'a str, &'a str)>;
    fn slice_name(&self) -> Option<(&'a str, &'a str)>;
    fn slice_space(&self) -> Option<(&'a str, &'a str)>;
}

impl<'a> XmlStr<'a> for &'a str {
    fn slice_at(&self, position: uint) -> (&'a str, &'a str) {
        (self.slice_to(position), self.slice_from(position))
    }

    fn slice_until(&self, s: &str) -> Option<(&'a str, &'a str)> {
        match self.find_str(s) {
            Some(position) => Some(self.slice_at(position)),
            None => None
        }
    }

    fn slice_literal(&self, expected: &str) -> Option<(&'a str, &'a str)> {
        if self.starts_with(expected) {
            Some(self.slice_at(expected.len()))
        } else {
            None
        }
    }

    fn slice_start_rest(&self,
                        is_first: |char| -> bool,
                        is_rest: |char| -> bool)
                        -> Option<(&'a str, &'a str)>
    {
        let mut positions = self.char_indices();

        match positions.next() {
            Some((_, c)) if is_first(c) => (),
            Some((_, _)) => return None,
            None => return None,
        };

        let mut positions = positions.skip_while(|&(_, c)| is_rest(c));
        match positions.next() {
            Some((offset, _)) => Some(self.slice_at(offset)),
            None => Some((self.clone(), "")),
        }
    }

    fn slice_name(&self) -> Option<(&'a str, &'a str)> {
        self.slice_start_rest(|c| c.is_name_start_char(), |c| c.is_name_char())
    }

    fn slice_space(&self) -> Option<(&'a str, &'a str)> {
        self.slice_start_rest(|c| c.is_space_char(), |c| c.is_space_char())
    }
}

trait XmlChar {
    fn is_name_start_char(&self) -> bool;
    fn is_name_char(&self) -> bool;
    fn is_space_char(&self) -> bool;
}

impl XmlChar for char {
    fn is_name_start_char(&self) -> bool {
        match *self {
            ':'                        |
            'A'..'Z'                   |
            '_'                        |
            'a'..'z'                   |
            '\U000000C0'..'\U000000D6' |
            '\U000000D8'..'\U000000F6' |
            '\U000000F8'..'\U000002FF' |
            '\U00000370'..'\U0000037D' |
            '\U0000037F'..'\U00001FFF' |
            '\U0000200C'..'\U0000200D' |
            '\U00002070'..'\U0000218F' |
            '\U00002C00'..'\U00002FEF' |
            '\U00003001'..'\U0000D7FF' |
            '\U0000F900'..'\U0000FDCF' |
            '\U0000FDF0'..'\U0000FFFD' |
            '\U00010000'..'\U000EFFFF' => true,
            _ => false,
        }
    }

    fn is_name_char(&self) -> bool {
        if self.is_name_start_char() { return true; }
        match *self {
            '-'                |
            '.'                |
            '0'..'9'           |
            '\u00B7'           |
            '\u0300'..'\u036F' |
            '\u203F'..'\u2040' => true,
            _ => false
        }
    }

    fn is_space_char(&self) -> bool {
        match *self {
            '\x20' |
            '\x09' |
            '\x0D' |
            '\x0A' => true,
            _ => false,
        }
    }
}

trait Hax {
    fn first_child(&self) -> Option<RootChild>;
}

impl Hax for Root {
    fn first_child(&self) -> Option<RootChild> {
        self.children().remove(0)
    }
}

trait Hax2 {
    fn first_child(&self) -> Option<ElementChild>;
}

impl Hax2 for Element {
    fn first_child(&self) -> Option<ElementChild> {
        self.children().remove(0)
    }
}

#[test]
fn parses_a_document_with_a_single_element() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello />");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.name().as_slice(), "hello");
}

#[test]
fn parses_an_element_with_an_attribute() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello scope='world'/>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.get_attribute("scope").unwrap().as_slice(), "world");
}

#[test]
fn parses_an_element_with_an_attribute_using_double_quotes() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello scope=\"world\"/>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.get_attribute("scope").unwrap().as_slice(), "world");
}

#[test]
fn parses_an_element_with_multiple_attributes() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello scope=\"world\" happy='true'/>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.get_attribute("scope").unwrap().as_slice(), "world");
    assert_eq!(top.get_attribute("happy").unwrap().as_slice(), "true");
}

#[test]
fn parses_an_element_that_is_not_self_closing() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello></hello>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.name().as_slice(), "hello");
}

#[test]
fn parses_nested_elements() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello><world/></hello>");
    let nested = doc.root().first_child().unwrap().element().unwrap().first_child().unwrap().element().unwrap();

    assert_eq!(nested.name().as_slice(), "world");
}
<commit_msg>Parse nested elements and attributes on those elements<commit_after>use super::{Document,Root,RootChild,Element,ElementChild};

struct Parser;

struct ParsedElement<'a> {
    name: &'a str,
    attributes: Vec<ParsedAttribute<'a>>,
    children: Vec<ParsedElement<'a>>,
}

struct ParsedAttribute<'a> {
    name: &'a str,
    value: &'a str,
}

macro_rules! try_parse(
    ($e:expr) => ({
        match $e {
            None => return None,
            Some(x) => x,
        }
    })
)

// Pattern: 0-or-1
macro_rules! optional_parse(
    ($f:expr, $start:expr) => ({
        match $f {
            None => (None, $start),
            Some((value, next)) => (Some(value), next),
        }
    })
)

impl Parser {
    fn new() -> Parser {
        Parser
    }

    fn parse_preamble<'a>(&self, xml: &'a str) -> &'a str {
        // Parse the preamble
        let idx = xml.find_str("?>").expect("No preamble end");
        let end_of_preamble = idx + "?>".len();
        xml.slice_from(end_of_preamble)
    }

    fn optional_space<'a>(&self, xml: &'a str) -> &'a str {
        match xml.slice_space() {
            Some((_, next_xml)) => next_xml,
            None => xml,
        }
    }

    fn parse_attribute_value_quote<'a>(&self, xml: &'a str, quote: &str) -> Option<(&'a str, &'a str)> {
        let (_, xml) = match xml.slice_literal(quote) {
            None => return None,
            Some(x) => x,
        };
        // TODO: don't consume & or <
        let (value, xml) = xml.slice_until(quote).expect("No value");
        let (_, xml) = xml.slice_literal(quote).expect("No quote");

        Some((value, xml))
    }

    fn parse_attribute<'a>(&self, xml: &'a str) -> Option<(ParsedAttribute<'a>, &'a str)> {
        let (name, xml) = match xml.slice_name() {
            Some(x) => x,
            None => return None,
        };

        let xml = self.optional_space(xml);
        let (_, xml) = xml.slice_literal("=").expect("No equal sign");
        let xml = self.optional_space(xml);

        // Pattern: alternate
        let (value, xml) = match self.parse_attribute_value_quote(xml, "'") {
            Some(x) => x,
            None => match self.parse_attribute_value_quote(xml, "\"") {
                Some(x) => x,
                None => fail!("No attribute value"),
            },
        };

        Some((ParsedAttribute{name: name, value: value}, xml))
    }

    fn parse_attributes<'a>(&self, xml: &'a str) -> (Vec<ParsedAttribute<'a>>, &'a str) {
        let mut xml = xml;
        let mut attrs = Vec::new();

        // Pattern: zero-or-more
        // On failure, return the end of the last successful parse
        loop {
            let (_, after_space) = match xml.slice_space() {
                None => return (attrs, xml),
                Some(x) => x,
            };

            xml = match self.parse_attribute(after_space) {
                None => return (attrs, xml),
                Some((attr, after_attr)) => {
                    attrs.push(attr);
                    after_attr
                },
            };
        }
    }

    fn parse_empty_element<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        let (_, xml) = try_parse!(xml.slice_literal("<"));
        let (name, xml) = try_parse!(xml.slice_name());
        let (attrs, xml) = self.parse_attributes(xml);
        let xml = self.optional_space(xml);
        let (_, xml) = try_parse!(xml.slice_literal("/>"));

        Some((ParsedElement{name: name, attributes: attrs, children: Vec::new()}, xml))
    }

    fn parse_element_start<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        let (_, xml) = try_parse!(xml.slice_literal("<"));
        let (name, xml) = try_parse!(xml.slice_name());
        let (attrs, xml) = self.parse_attributes(xml);
        let xml = self.optional_space(xml);
        let (_, xml) = try_parse!(xml.slice_literal(">"));

        Some((ParsedElement{name: name, attributes: attrs, children: Vec::new()}, xml))
    }

    fn parse_element_end<'a>(&self, xml: &'a str) -> Option<(&'a str, &'a str)> {
        let (_, xml) = try_parse!(xml.slice_literal("</"));
        let (name, xml) = try_parse!(xml.slice_name());
        let xml = self.optional_space(xml);
        let (_, xml) = try_parse!(xml.slice_literal(">"));
        Some((name, xml))
    }

    fn parse_non_empty_element<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        let (mut element, xml) = try_parse!(self.parse_element_start(xml));
        let (child, xml) = optional_parse!(self.parse_element(xml), xml);
        let (name, xml) = try_parse!(self.parse_element_end(xml));

        if element.name != name {
            fail!("tags do not match!");
        }

        child.map(|c| element.children.push(c));

        Some((element, xml))
    }

    fn parse_element<'a>(&self, xml: &'a str) -> Option<(ParsedElement<'a>, &'a str)> {
        // Pattern: alternate
        match self.parse_empty_element(xml) {
            Some(x) => Some(x),
            None => match self.parse_non_empty_element(xml) {
                Some(x) => Some(x),
                None => None,
            },
        }
    }

    fn hydrate_element(&self, doc: Document, element_data: ParsedElement) -> Element {
        let element = doc.new_element(element_data.name.to_string());
        for attr in element_data.attributes.iter() {
            element.set_attribute(attr.name.to_string(), attr.value.to_string());
        }
        for child in element_data.children.move_iter() {
            element.append_child(self.hydrate_element(doc.clone(), child));
        }
        element
    }

    fn hydrate_parsed_data(&self, element_data: ParsedElement) -> Document {
        let doc = Document::new();

        doc.root().append_child(self.hydrate_element(doc.clone(), element_data));

        doc
    }

    fn parse(&self, xml: &str) -> Document {
        let after_preamble = self.parse_preamble(xml);

        let (element, _tail) = self.parse_element(after_preamble).expect("no element");

        self.hydrate_parsed_data(element)
    }
}

trait XmlStr<'a> {
    fn slice_at(&self, position: uint) -> (&'a str, &'a str);
    fn slice_until(&self, s: &str) -> Option<(&'a str, &'a str)>;
    fn slice_literal(&self, expected: &str) -> Option<(&'a str, &'a str)>;
    fn slice_start_rest(&self, is_first: |char| -> bool, is_rest: |char| -> bool) -> Option<(&'a str, &'a str)>;
    fn slice_name(&self) -> Option<(&'a str, &'a str)>;
    fn slice_space(&self) -> Option<(&'a str, &'a str)>;
}

impl<'a> XmlStr<'a> for &'a str {
    fn slice_at(&self, position: uint) -> (&'a str, &'a str) {
        (self.slice_to(position), self.slice_from(position))
    }

    fn slice_until(&self, s: &str) -> Option<(&'a str, &'a str)> {
        match self.find_str(s) {
            Some(position) => Some(self.slice_at(position)),
            None => None
        }
    }

    fn slice_literal(&self, expected: &str) -> Option<(&'a str, &'a str)> {
        if self.starts_with(expected) {
            Some(self.slice_at(expected.len()))
        } else {
            None
        }
    }

    fn slice_start_rest(&self,
                        is_first: |char| -> bool,
                        is_rest: |char| -> bool)
                        -> Option<(&'a str, &'a str)>
    {
        let mut positions = self.char_indices();

        match positions.next() {
            Some((_, c)) if is_first(c) => (),
            Some((_, _)) => return None,
            None => return None,
        };

        let mut positions = positions.skip_while(|&(_, c)| is_rest(c));
        match positions.next() {
            Some((offset, _)) => Some(self.slice_at(offset)),
            None => Some((self.clone(), "")),
        }
    }

    fn slice_name(&self) -> Option<(&'a str, &'a str)> {
        self.slice_start_rest(|c| c.is_name_start_char(), |c| c.is_name_char())
    }

    fn slice_space(&self) -> Option<(&'a str, &'a str)> {
        self.slice_start_rest(|c| c.is_space_char(), |c| c.is_space_char())
    }
}

trait XmlChar {
    fn is_name_start_char(&self) -> bool;
    fn is_name_char(&self) -> bool;
    fn is_space_char(&self) -> bool;
}

impl XmlChar for char {
    fn is_name_start_char(&self) -> bool {
        match *self {
            ':'                        |
            'A'..'Z'                   |
            '_'                        |
            'a'..'z'                   |
            '\U000000C0'..'\U000000D6' |
            '\U000000D8'..'\U000000F6' |
            '\U000000F8'..'\U000002FF' |
            '\U00000370'..'\U0000037D' |
            '\U0000037F'..'\U00001FFF' |
            '\U0000200C'..'\U0000200D' |
            '\U00002070'..'\U0000218F' |
            '\U00002C00'..'\U00002FEF' |
            '\U00003001'..'\U0000D7FF' |
            '\U0000F900'..'\U0000FDCF' |
            '\U0000FDF0'..'\U0000FFFD' |
            '\U00010000'..'\U000EFFFF' => true,
            _ => false,
        }
    }

    fn is_name_char(&self) -> bool {
        if self.is_name_start_char() { return true; }
        match *self {
            '-'                |
            '.'                |
            '0'..'9'           |
            '\u00B7'           |
            '\u0300'..'\u036F' |
            '\u203F'..'\u2040' => true,
            _ => false
        }
    }

    fn is_space_char(&self) -> bool {
        match *self {
            '\x20' |
            '\x09' |
            '\x0D' |
            '\x0A' => true,
            _ => false,
        }
    }
}

trait Hax {
    fn first_child(&self) -> Option<RootChild>;
}

impl Hax for Root {
    fn first_child(&self) -> Option<RootChild> {
        self.children().remove(0)
    }
}

trait Hax2 {
    fn first_child(&self) -> Option<ElementChild>;
}

impl Hax2 for Element {
    fn first_child(&self) -> Option<ElementChild> {
        self.children().remove(0)
    }
}

#[test]
fn parses_a_document_with_a_single_element() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello />");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.name().as_slice(), "hello");
}

#[test]
fn parses_an_element_with_an_attribute() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello scope='world'/>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.get_attribute("scope").unwrap().as_slice(), "world");
}

#[test]
fn parses_an_element_with_an_attribute_using_double_quotes() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello scope=\"world\"/>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.get_attribute("scope").unwrap().as_slice(), "world");
}

#[test]
fn parses_an_element_with_multiple_attributes() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello scope=\"world\" happy='true'/>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.get_attribute("scope").unwrap().as_slice(), "world");
    assert_eq!(top.get_attribute("happy").unwrap().as_slice(), "true");
}

#[test]
fn parses_an_element_that_is_not_self_closing() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello></hello>");
    let top = doc.root().first_child().unwrap().element().unwrap();

    assert_eq!(top.name().as_slice(), "hello");
}

#[test]
fn parses_nested_elements() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello><world/></hello>");
    let nested = doc.root().first_child().unwrap().element().unwrap().first_child().unwrap().element().unwrap();

    assert_eq!(nested.name().as_slice(), "world");
}

#[test]
fn parses_multiply_nested_elements() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello><awesome><world/></awesome></hello>");
    let hello = doc.root().first_child().unwrap().element().unwrap();
    let awesome = hello.first_child().unwrap().element().unwrap();
    let world = awesome.first_child().unwrap().element().unwrap();

    assert_eq!(world.name().as_slice(), "world");
}

#[test]
fn parses_nested_elements_with_attributes() {
    let parser = Parser::new();
    let doc = parser.parse("<?xml version='1.0' ?><hello><world name='Earth'/></hello>");
    let hello = doc.root().first_child().unwrap().element().unwrap();
    let world = hello.first_child().unwrap().element().unwrap();

    assert_eq!(world.get_attribute("name").unwrap().as_slice(), "Earth");
}
<|endoftext|>


<commit_before>use linked_hash_map::LinkedHashMap;

use crate::generation::typescript::{collapse_option, is_ts_identifier};
use crate::options::Options;
use crate::shape::{self, Shape};

pub struct Ctxt {
    options: Options,
    indent_level: usize,
}

pub type Ident = String;
pub type Code = String;

pub fn typescript_type_alias(name: &str, shape: &Shape, options: Options) -> (Ident, Option<Code>) {
    let mut ctxt = Ctxt {
        options,
        indent_level: 1,
    };

    let mut code = type_from_shape(&mut ctxt, shape);

    code = format!("export type {} = {};\n\n", name, code);
    (name.to_string(), Some(code))
}

fn type_from_shape(ctxt: &mut Ctxt, shape: &Shape) -> Code {
    use crate::shape::Shape::*;
    match *shape {
        Null | Any | Bottom => "any".into(),
        Bool => "boolean".into(),
        StringT => "string".into(),
        Integer => "number".into(),
        Floating => "number".into(),
        Tuple(ref shapes, _n) => {
            let folded = shape::fold_shapes(shapes.clone());
            if folded == Any && shapes.iter().any(|s| s != &Any) {
                generate_tuple_type(ctxt, shapes)
            } else {
                generate_vec_type(ctxt, &folded)
            }
        }
        VecT { elem_type: ref e } => generate_vec_type(ctxt, e),
        Struct { fields: ref map } => generate_struct_from_field_shapes(ctxt, map),
        MapT { val_type: ref v } => generate_map_type(ctxt, v),
        Opaque(ref t) => t.clone(),
        Optional(ref e) => {
            let inner = type_from_shape(ctxt, e);
            if ctxt.options.use_default_for_missing_fields {
                inner
            } else {
                format!("{} | undefined", inner)
            }
        }
    }
}

fn generate_vec_type(ctxt: &mut Ctxt, shape: &Shape) -> Code {
    let inner = type_from_shape(ctxt, &shape);
    format!("Array<{}>", inner)
}

fn generate_map_type(ctxt: &mut Ctxt, shape: &Shape) -> Code {
    let inner = type_from_shape(ctxt, &shape);
    format!("{{ [key: string]: {} }}", inner)
}

fn generate_tuple_type(ctxt: &mut Ctxt, shapes: &[Shape]) -> Code {
    let mut types = Vec::new();

    for shape in shapes {
        let typ = type_from_shape(ctxt, shape);
        types.push(typ);
    }

    format!("[{}]", types.join(", "))
}

fn generate_struct_from_field_shapes(ctxt: &mut Ctxt, map: &LinkedHashMap<String, Shape>) -> Code {
    let fields: Vec<Code> = map
        .iter()
        .map(|(name, typ)| {
            let (was_optional, collapsed) = collapse_option(typ);

            ctxt.indent_level += 1;
            let field_type = type_from_shape(ctxt, collapsed);
            ctxt.indent_level -= 1;

            let escape_name = !is_ts_identifier(name);

            format!(
                "{}{}{}{}{}: {};",
                "    ".repeat(ctxt.indent_level),
                if escape_name { "\"" } else { "" },
                name,
                if escape_name { "\"" } else { "" },
                if was_optional { "?" } else { "" },
                field_type
            )
        })
        .collect();

    let mut code = format!("{{\n");

    if !fields.is_empty() {
        code += &fields.join("\n");
        code += "\n";
        code += &"    ".repeat(ctxt.indent_level - 1);
    }
    code += "}";

    code
}
<commit_msg>ts/alias: Fix incorrect indent<commit_after>use linked_hash_map::LinkedHashMap;

use crate::generation::typescript::{collapse_option, is_ts_identifier};
use crate::options::Options;
use crate::shape::{self, Shape};

pub struct Ctxt {
    options: Options,
    indent_level: usize,
}

pub type Ident = String;
pub type Code = String;

pub fn typescript_type_alias(name: &str, shape: &Shape, options: Options) -> (Ident, Option<Code>) {
    let mut ctxt = Ctxt {
        options,
        indent_level: 1,
    };

    let mut code = type_from_shape(&mut ctxt, shape);

    code = format!("export type {} = {};\n\n", name, code);
    (name.to_string(), Some(code))
}

fn type_from_shape(ctxt: &mut Ctxt, shape: &Shape) -> Code {
    use crate::shape::Shape::*;
    match *shape {
        Null | Any | Bottom => "any".into(),
        Bool => "boolean".into(),
        StringT => "string".into(),
        Integer => "number".into(),
        Floating => "number".into(),
        Tuple(ref shapes, _n) => {
            let folded = shape::fold_shapes(shapes.clone());
            if folded == Any && shapes.iter().any(|s| s != &Any) {
                generate_tuple_type(ctxt, shapes)
            } else {
                generate_vec_type(ctxt, &folded)
            }
        }
        VecT { elem_type: ref e } => generate_vec_type(ctxt, e),
        Struct { fields: ref map } => generate_struct_from_field_shapes(ctxt, map),
        MapT { val_type: ref v } => generate_map_type(ctxt, v),
        Opaque(ref t) => t.clone(),
        Optional(ref e) => {
            let inner = type_from_shape(ctxt, e);
            if ctxt.options.use_default_for_missing_fields {
                inner
            } else {
                format!("{} | undefined", inner)
            }
        }
    }
}

fn generate_vec_type(ctxt: &mut Ctxt, shape: &Shape) -> Code {
    let inner = type_from_shape(ctxt, &shape);
    format!("Array<{}>", inner)
}

fn generate_map_type(ctxt: &mut Ctxt, shape: &Shape) -> Code {
    let inner = type_from_shape(ctxt, &shape);
    format!("{{ [key: string]: {} }}", inner)
}

fn generate_tuple_type(ctxt: &mut Ctxt, shapes: &[Shape]) -> Code {
    let mut types = Vec::new();

    for shape in shapes {
        let typ = type_from_shape(ctxt, shape);
        types.push(typ);
    }

    format!("[{}]", types.join(", "))
}

fn generate_struct_from_field_shapes(ctxt: &mut Ctxt, map: &LinkedHashMap<String, Shape>) -> Code {
    let fields: Vec<Code> = map
        .iter()
        .map(|(name, typ)| {
            let (was_optional, collapsed) = collapse_option(typ);

            ctxt.indent_level += 1;
            let field_type = type_from_shape(ctxt, collapsed);
            ctxt.indent_level -= 1;

            let escape_name = !is_ts_identifier(name);

            format!(
                "{}{}{}{}{}: {};",
                "    ".repeat(ctxt.indent_level),
                if escape_name { "\"" } else { "" },
                name,
                if escape_name { "\"" } else { "" },
                if was_optional { "?" } else { "" },
                field_type
            )
        })
        .collect();

    let mut code = format!("{{\n");

    if !fields.is_empty() {
        code += &fields.join("\n");
        code += "\n";
    }
    code += &"    ".repeat(ctxt.indent_level - 1);
    code += "}";

    code
}
<|endoftext|>


<commit_before>//! Primer is a library for simple bare-metal ARM programming.

#![feature(lang_items)]
#![feature(start)]
#![feature(unique)]
#![feature(asm)]
#![feature(core_intrinsics)]
#![no_std]
#![crate_type="staticlib"]

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

pub mod gpio;
pub mod lm4f120h5qr;
pub mod launchpad;

extern "C" {
    static mut _start_data_flash: usize;
    static mut _start_data: usize;
    static mut _end_data: usize;
    static mut _bss_start: usize;
    static mut _bss_end: usize;
    fn _stack_top();
	fn primer_start();
}

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

#[link_section=".nvic_table"]
#[no_mangle]
pub static ISR_VECTORS: [Option<unsafe extern "C" fn()>; 155] = [
    // Stack pointer
    Some(_stack_top),
    // Reset
    Some(startup),
    // NMI
    Some(isr_nmi),
    // Hard Fault
    Some(isr_hardfault),
    // CM3 Memory Management Fault
    Some(isr_mmfault),
    // CM3 Bus Fault
    Some(isr_busfault),
    // CM3 Usage Fault
    Some(isr_usagefault),
    // Reserved - Used as NXP Checksum
    None,
    // Reserved
    None,
    // Reserved
    None,
    // Reserved
    None,
    // SVCall
    Some(isr_svcall),
    // Reserved for debug
    Some(isr_debugmon),
    // Reserved
    None,
    // PendSV
    Some(isr_pendsv),
    // SysTick
    Some(isr_systick),
    // GPIO Port A                      16
    Some(isr_empty_def),
    // GPIO Port B                      17
    Some(isr_empty_def),
    // GPIO Port C                      18
    Some(isr_empty_def),
    // GPIO Port D                      19
    Some(isr_empty_def),
    // GPIO Port E                      20
    Some(isr_empty_def),
    // UART 0                           21
    Some(isr_empty_def),
    // UART 1                           22
    Some(isr_empty_def),
    // SSI 0                            23
    Some(isr_empty_def),
    // I2C 0                            24
    Some(isr_empty_def),
    // Reserved                         25
    None,
    // Reserved                         26
    None,
    // Reserved                         27
    None,
    // Reserved                         28
    None,
    // Reserved                         29
    None,
    // ADC 0 Seq 0                      30
    Some(isr_empty_def),
    // ADC 0 Seq 1                      31
    Some(isr_empty_def),
    // ADC 0 Seq 2                      32
    Some(isr_empty_def),
    // ADC 0 Seq 3                      33
    Some(isr_empty_def),
    // WDT 0 and 1                      34
    Some(isr_empty_def),
    // 16/32 bit timer 0 A              35
    Some(isr_empty_def),
    // 16/32 bit timer 0 B              36
    Some(isr_empty_def),
    // 16/32 bit timer 1 A              37
    Some(isr_empty_def),
    // 16/32 bit timer 1 B              38
    Some(isr_empty_def),
    // 16/32 bit timer 2 A              39
    Some(isr_empty_def),
    // 16/32 bit timer 2 B              40
    Some(isr_empty_def),
    // Analog comparator 0              41
    Some(isr_empty_def),
    // Analog comparator 1              42
    Some(isr_empty_def),
    // Reserved                         43
    None,
    // System control                   44
    Some(isr_empty_def),
    // Flash + EEPROM control           45
    Some(isr_empty_def),
    // GPIO Port F                      46
    Some(isr_empty_def),
    // Reserved                         47
    None,
    // Reserved                         48
    None,
    // UART 2                           49
    Some(isr_empty_def),
    // SSI 1                            50
    Some(isr_empty_def),
    // 16/32 bit timer 3 A              51
    Some(isr_empty_def),
    // 16/32 bit timer 3 B              52
    Some(isr_empty_def),
    // I2C 1                            53
    Some(isr_empty_def),
    // Reserved                         54
    None,
    // CAN 0                            55
    Some(isr_empty_def),
    // Reserved                         56
    None,
    // Reserved                         57
    None,
    // Reserved                         58
    None,
    // Hibernation module               59
    Some(isr_empty_def),
    // USB                              60
    Some(isr_empty_def),
    // Reserved                         61
    None,
    // UDMA SW                          62
    Some(isr_empty_def),
    // UDMA Error                       63
    Some(isr_empty_def),
    // ADC 1 Seq 0                      64
    Some(isr_empty_def),
    // ADC 1 Seq 1                      65
    Some(isr_empty_def),
    // ADC 1 Seq 2                      66
    Some(isr_empty_def),
    // ADC 1 Seq 3                      67
    Some(isr_empty_def),
    // Reserved                         68
    None,
    // Reserved                         69
    None,
    // Reserved                         70
    None,
    // Reserved                         71
    None,
    // Reserved                         72
    None,
    // SSI 2                            73
    Some(isr_empty_def),
    // SSI 2                            74
    Some(isr_empty_def),
    // UART 3                           75
    Some(isr_empty_def),
    // UART 4                           76
    Some(isr_empty_def),
    // UART 5                           77
    Some(isr_empty_def),
    // UART 6                           78
    Some(isr_empty_def),
    // UART 7                           79
    Some(isr_empty_def),
    // Reserved                         80
    None,
    // Reserved                         81
    None,
    // Reserved                         82
    None,
    // Reserved                         83
    None,
    // I2C 2                            84
    Some(isr_empty_def),
    // I2C 4                            85
    Some(isr_empty_def),
    // 16/32 bit timer 4 A              86
    Some(isr_empty_def),
    // 16/32 bit timer 4 B              87
    Some(isr_empty_def),
    // Reserved                         88
    None,
    // Reserved                         89
    None,
    // Reserved                         90
    None,
    // Reserved                         91
    None,
    // Reserved                         92
    None,
    // Reserved                         93
    None,
    // Reserved                         94
    None,
    // Reserved                         95
    None,
    // Reserved                         96
    None,
    // Reserved                         97
    None,
    // Reserved                         98
    None,
    // Reserved                         99
    None,
    // Reserved                         100
    None,
    // Reserved                         101
    None,
    // Reserved                         102
    None,
    // Reserved                         103
    None,
    // Reserved                         104
    None,
    // Reserved                         105
    None,
    // Reserved                         106
    None,
    // Reserved                         107
    None,
    // 16/32 bit timer 5 A              108
    Some(isr_empty_def),
    // 16/32 bit timer 5 B              109
    Some(isr_empty_def),
    // 32/64 bit timer 0 A              110
    Some(isr_empty_def),
    // 32/64 bit timer 0 B              111
    Some(isr_empty_def),
    // 32/64 bit timer 1 A              112
    Some(isr_empty_def),
    // 32/64 bit timer 1 B              113
    Some(isr_empty_def),
    // 32/64 bit timer 2 A              114
    Some(isr_empty_def),
    // 32/64 bit timer 2 B              115
    Some(isr_empty_def),
    // 32/64 bit timer 3 A              116
    Some(isr_empty_def),
    // 32/64 bit timer 3 B              117
    Some(isr_empty_def),
    // 32/64 bit timer 4 A              118
    Some(isr_empty_def),
    // 32/64 bit timer 4 B              119
    Some(isr_empty_def),
    // 32/64 bit timer 5 A              120
    Some(isr_empty_def),
    // 32/64 bit timer 5 B              121
    Some(isr_empty_def),
    // System Exception                 122
    Some(isr_empty_def),
    // Reserved                         123
    None,
    // Reserved                         124
    None,
    // Reserved                         125
    None,
    // Reserved                         126
    None,
    // Reserved                         127
    None,
    // Reserved                         128
    None,
    // Reserved                         129
    None,
    // Reserved                         130
    None,
    // Reserved                         131
    None,
    // Reserved                         132
    None,
    // Reserved                         133
    None,
    // Reserved                         134
    None,
    // Reserved                         135
    None,
    // Reserved                         136
    None,
    // Reserved                         137
    None,
    // Reserved                         138
    None,
    // Reserved                         139
    None,
    // Reserved                         140
    None,
    // Reserved                         141
    None,
    // Reserved                         142
    None,
    // Reserved                         143
    None,
    // Reserved                         144
    None,
    // Reserved                         145
    None,
    // Reserved                         146
    None,
    // Reserved                         147
    None,
    // Reserved                         148
    None,
    // Reserved                         149
    None,
    // Reserved                         150
    None,
    // Reserved                         151
    None,
    // Reserved                         152
    None,
    // Reserved                         153
    None,
    // Reserved                         154
    None];

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Busy-waits for the given period.
///
/// Currently this function spins with a empirical number
/// of NOPS per millisecond. It should really use a timer.
///
/// * `ms` - The period to wait, in milliseconds
pub fn delay(ms: i32) {
    for _ in 0..ms * 150 {
        unsafe {
            asm!("NOP");
        }
    }
}

/// Performs what you might otherwise call 'C Startup'
///
/// Copies global .data init from flash to SRAM and then
/// zeros the bss segment.
pub unsafe extern "C" fn startup() {
    let mut src: *mut usize = &mut _start_data_flash;
    let mut dest: *mut usize = &mut _start_data;

    while dest < &mut _end_data as *mut usize {
        *dest = *src;
        dest = ((dest as usize) + 4) as *mut usize;
        src = ((src as usize) + 4) as *mut usize;
    }

    dest = &mut _bss_start as *mut usize;

    while dest < &mut _end_data as *mut usize {
        *dest = 0;
        dest = ((dest as usize) + 4) as *mut usize;
    }

    primer_start();
}

/// Required by the compiler.
#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr0() -> () {
    loop {}
}

/// Required by the compiler.
#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr1() -> () {
    loop {}
}

/// Required by the compiler.
#[lang="eh_personality"]
extern "C" fn eh_personality() {

}

/// Entry point of panic from the libcore crate.
///
/// Required by the compiler.
#[lang="panic_fmt"]
#[no_mangle]
pub extern "C" fn rust_begin_unwind(_fmt: &core::fmt::Arguments,
                                    _file_line: &(&'static str, usize))
                                    -> ! {
    loop {}
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

unsafe extern "C" fn isr_nmi() {
    loop {}
}

unsafe extern "C" fn isr_hardfault() {
    loop {}
}

unsafe extern "C" fn isr_mmfault() {
    loop {}
}

unsafe extern "C" fn isr_busfault() {
    loop {}
}

unsafe extern "C" fn isr_usagefault() {
    loop {}
}

unsafe extern "C" fn isr_svcall() {
    loop {}
}

unsafe extern "C" fn isr_debugmon() {
    loop {}
}

unsafe extern "C" fn isr_pendsv() {
    loop {}
}

unsafe extern "C" fn isr_systick() {
    loop {}
}

unsafe extern "C" fn isr_empty_def() {
    loop {}
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>More documentation, from Cortex-M4 Devices Generic User Guide.<commit_after>//! Primer is a library for simple bare-metal ARM programming.

#![feature(lang_items)]
#![feature(start)]
#![feature(unique)]
#![feature(asm)]
#![feature(core_intrinsics)]
#![no_std]
#![crate_type="staticlib"]

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

pub mod gpio;
pub mod lm4f120h5qr;
pub mod launchpad;

extern "C" {
    static mut _start_data_flash: usize;
    static mut _start_data: usize;
    static mut _end_data: usize;
    static mut _bss_start: usize;
    static mut _bss_end: usize;
    fn _stack_top();
    fn primer_start();
}

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

#[link_section=".nvic_table"]
#[no_mangle]
pub static ISR_VECTORS: [Option<unsafe extern "C" fn()>; 155] = [
    // Stack pointer
    Some(_stack_top),
    // Reset
    Some(startup),
    // NMI
    Some(isr_nmi),
    // Hard Fault
    Some(isr_hardfault),
    // CM3 Memory Management Fault
    Some(isr_mmfault),
    // CM3 Bus Fault
    Some(isr_busfault),
    // CM3 Usage Fault
    Some(isr_usagefault),
    // Reserved - Used as NXP Checksum
    None,
    // Reserved
    None,
    // Reserved
    None,
    // Reserved
    None,
    // SVCall
    Some(isr_svcall),
    // Reserved for debug
    Some(isr_debugmon),
    // Reserved
    None,
    // PendSV
    Some(isr_pendsv),
    // SysTick
    Some(isr_systick),
    // GPIO Port A                      16
    Some(isr_empty_def),
    // GPIO Port B                      17
    Some(isr_empty_def),
    // GPIO Port C                      18
    Some(isr_empty_def),
    // GPIO Port D                      19
    Some(isr_empty_def),
    // GPIO Port E                      20
    Some(isr_empty_def),
    // UART 0                           21
    Some(isr_empty_def),
    // UART 1                           22
    Some(isr_empty_def),
    // SSI 0                            23
    Some(isr_empty_def),
    // I2C 0                            24
    Some(isr_empty_def),
    // Reserved                         25
    None,
    // Reserved                         26
    None,
    // Reserved                         27
    None,
    // Reserved                         28
    None,
    // Reserved                         29
    None,
    // ADC 0 Seq 0                      30
    Some(isr_empty_def),
    // ADC 0 Seq 1                      31
    Some(isr_empty_def),
    // ADC 0 Seq 2                      32
    Some(isr_empty_def),
    // ADC 0 Seq 3                      33
    Some(isr_empty_def),
    // WDT 0 and 1                      34
    Some(isr_empty_def),
    // 16/32 bit timer 0 A              35
    Some(isr_empty_def),
    // 16/32 bit timer 0 B              36
    Some(isr_empty_def),
    // 16/32 bit timer 1 A              37
    Some(isr_empty_def),
    // 16/32 bit timer 1 B              38
    Some(isr_empty_def),
    // 16/32 bit timer 2 A              39
    Some(isr_empty_def),
    // 16/32 bit timer 2 B              40
    Some(isr_empty_def),
    // Analog comparator 0              41
    Some(isr_empty_def),
    // Analog comparator 1              42
    Some(isr_empty_def),
    // Reserved                         43
    None,
    // System control                   44
    Some(isr_empty_def),
    // Flash + EEPROM control           45
    Some(isr_empty_def),
    // GPIO Port F                      46
    Some(isr_empty_def),
    // Reserved                         47
    None,
    // Reserved                         48
    None,
    // UART 2                           49
    Some(isr_empty_def),
    // SSI 1                            50
    Some(isr_empty_def),
    // 16/32 bit timer 3 A              51
    Some(isr_empty_def),
    // 16/32 bit timer 3 B              52
    Some(isr_empty_def),
    // I2C 1                            53
    Some(isr_empty_def),
    // Reserved                         54
    None,
    // CAN 0                            55
    Some(isr_empty_def),
    // Reserved                         56
    None,
    // Reserved                         57
    None,
    // Reserved                         58
    None,
    // Hibernation module               59
    Some(isr_empty_def),
    // USB                              60
    Some(isr_empty_def),
    // Reserved                         61
    None,
    // UDMA SW                          62
    Some(isr_empty_def),
    // UDMA Error                       63
    Some(isr_empty_def),
    // ADC 1 Seq 0                      64
    Some(isr_empty_def),
    // ADC 1 Seq 1                      65
    Some(isr_empty_def),
    // ADC 1 Seq 2                      66
    Some(isr_empty_def),
    // ADC 1 Seq 3                      67
    Some(isr_empty_def),
    // Reserved                         68
    None,
    // Reserved                         69
    None,
    // Reserved                         70
    None,
    // Reserved                         71
    None,
    // Reserved                         72
    None,
    // SSI 2                            73
    Some(isr_empty_def),
    // SSI 2                            74
    Some(isr_empty_def),
    // UART 3                           75
    Some(isr_empty_def),
    // UART 4                           76
    Some(isr_empty_def),
    // UART 5                           77
    Some(isr_empty_def),
    // UART 6                           78
    Some(isr_empty_def),
    // UART 7                           79
    Some(isr_empty_def),
    // Reserved                         80
    None,
    // Reserved                         81
    None,
    // Reserved                         82
    None,
    // Reserved                         83
    None,
    // I2C 2                            84
    Some(isr_empty_def),
    // I2C 4                            85
    Some(isr_empty_def),
    // 16/32 bit timer 4 A              86
    Some(isr_empty_def),
    // 16/32 bit timer 4 B              87
    Some(isr_empty_def),
    // Reserved                         88
    None,
    // Reserved                         89
    None,
    // Reserved                         90
    None,
    // Reserved                         91
    None,
    // Reserved                         92
    None,
    // Reserved                         93
    None,
    // Reserved                         94
    None,
    // Reserved                         95
    None,
    // Reserved                         96
    None,
    // Reserved                         97
    None,
    // Reserved                         98
    None,
    // Reserved                         99
    None,
    // Reserved                         100
    None,
    // Reserved                         101
    None,
    // Reserved                         102
    None,
    // Reserved                         103
    None,
    // Reserved                         104
    None,
    // Reserved                         105
    None,
    // Reserved                         106
    None,
    // Reserved                         107
    None,
    // 16/32 bit timer 5 A              108
    Some(isr_empty_def),
    // 16/32 bit timer 5 B              109
    Some(isr_empty_def),
    // 32/64 bit timer 0 A              110
    Some(isr_empty_def),
    // 32/64 bit timer 0 B              111
    Some(isr_empty_def),
    // 32/64 bit timer 1 A              112
    Some(isr_empty_def),
    // 32/64 bit timer 1 B              113
    Some(isr_empty_def),
    // 32/64 bit timer 2 A              114
    Some(isr_empty_def),
    // 32/64 bit timer 2 B              115
    Some(isr_empty_def),
    // 32/64 bit timer 3 A              116
    Some(isr_empty_def),
    // 32/64 bit timer 3 B              117
    Some(isr_empty_def),
    // 32/64 bit timer 4 A              118
    Some(isr_empty_def),
    // 32/64 bit timer 4 B              119
    Some(isr_empty_def),
    // 32/64 bit timer 5 A              120
    Some(isr_empty_def),
    // 32/64 bit timer 5 B              121
    Some(isr_empty_def),
    // System Exception                 122
    Some(isr_empty_def),
    // Reserved                         123
    None,
    // Reserved                         124
    None,
    // Reserved                         125
    None,
    // Reserved                         126
    None,
    // Reserved                         127
    None,
    // Reserved                         128
    None,
    // Reserved                         129
    None,
    // Reserved                         130
    None,
    // Reserved                         131
    None,
    // Reserved                         132
    None,
    // Reserved                         133
    None,
    // Reserved                         134
    None,
    // Reserved                         135
    None,
    // Reserved                         136
    None,
    // Reserved                         137
    None,
    // Reserved                         138
    None,
    // Reserved                         139
    None,
    // Reserved                         140
    None,
    // Reserved                         141
    None,
    // Reserved                         142
    None,
    // Reserved                         143
    None,
    // Reserved                         144
    None,
    // Reserved                         145
    None,
    // Reserved                         146
    None,
    // Reserved                         147
    None,
    // Reserved                         148
    None,
    // Reserved                         149
    None,
    // Reserved                         150
    None,
    // Reserved                         151
    None,
    // Reserved                         152
    None,
    // Reserved                         153
    None,
    // Reserved                         154
    None
];

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Busy-waits for the given period.
///
/// Currently this function spins with a empirical number
/// of NOPS per millisecond. It should really use a timer.
///
/// * `ms` - The period to wait, in milliseconds
pub fn delay(ms: i32) {
    for _ in 0..ms * 150 {
        unsafe {
            asm!("NOP");
        }
    }
}

/// Performs what you might otherwise call 'C Startup'
///
/// Copies global .data init from flash to SRAM and then
/// zeros the bss segment.
pub unsafe extern "C" fn startup() {
    let mut src: *mut usize = &mut _start_data_flash;
    let mut dest: *mut usize = &mut _start_data;

    while dest < &mut _end_data as *mut usize {
        *dest = *src;
        dest = ((dest as usize) + 4) as *mut usize;
        src = ((src as usize) + 4) as *mut usize;
    }

    dest = &mut _bss_start as *mut usize;

    while dest < &mut _end_data as *mut usize {
        *dest = 0;
        dest = ((dest as usize) + 4) as *mut usize;
    }

    primer_start();
}

/// Required by the compiler.
#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr0() -> () {
    loop {}
}

/// Required by the compiler.
#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr1() -> () {
    loop {}
}

/// Required by the compiler.
#[lang="eh_personality"]
extern "C" fn eh_personality() {}

/// Entry point of panic from the libcore crate.
///
/// Required by the compiler.
#[lang="panic_fmt"]
#[no_mangle]
pub extern "C" fn rust_begin_unwind(_fmt: &core::fmt::Arguments,
                                    _file_line: &(&'static str, usize))
                                    -> ! {
    loop {}
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

/// A Non Maskable Interrupt (NMI) can be signalled by a peripheral or
/// triggered by software. This is the highest priority exception other than
/// reset. It is permanently enabled and has a fixed priority of -2. NMIs
/// cannot be:
/// * masked or prevented from activation by any other exception
/// * preempted by any exception other than Reset.
unsafe extern "C" fn isr_nmi() {
    loop {}
}

/// A HardFault is an exception that occurs because of an error during
/// exception processing, or because an exception cannot be managed by any
/// other exception mechanism. HardFaults have a fixed priority of -1, meaning
/// they have higher priority than any exception with configurable priority.
unsafe extern "C" fn isr_hardfault() {
    loop {}
}

/// A MemManage fault is an exception that occurs because of a memory
/// protection related fault. The the fixed memory protection constraints
/// determines this fault, for both instruction and data memory transactions.
/// This fault is always used to abort instruction accesses to Execute Never
/// (XN) memory regions.
unsafe extern "C" fn isr_mmfault() {
    loop {}
}

/// A BusFault is an exception that occurs because of a memory related fault
/// for an instruction or data memory transaction. This might be from an error
/// detected on a bus in the memory system.
unsafe extern "C" fn isr_busfault() {
    loop {}
}

/// A UsageFault is an exception that occurs because of a fault related to instruction execution. This includes:
/// * an undefined instruction
/// * an illegal unaligned access
/// * invalid state on instruction execution
/// * an error on exception return.
/// The following can cause a UsageFault when the core is configured to report them:
/// * an unaligned address on word and halfword memory access
/// * division by zero.
unsafe extern "C" fn isr_usagefault() {
    loop {}
}

/// A supervisor call (SVC) is an exception that is triggered by the SVC
/// instruction. In an OS environment, applications can use SVC instructions
/// to access OS kernel functions and device drivers.
unsafe extern "C" fn isr_svcall() {
    loop {}
}

/// Debug monitor interrupt handler.
unsafe extern "C" fn isr_debugmon() {
    loop {}
}

/// PendSV is an interrupt-driven request for system-level service. In an OS
/// environment, use PendSV for context switching when no other exception is
/// active.
unsafe extern "C" fn isr_pendsv() {
    loop {}
}

/// A SysTick exception is an exception the system timer generates when it
/// reaches zero. Software can also generate a SysTick exception. In an OS
/// environment, the processor can use this exception as system tick.
unsafe extern "C" fn isr_systick() {
    loop {}
}

/// A place-holder ISR used when we have nothing better to use.
unsafe extern "C" fn isr_empty_def() {
    loop {}
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>