//! This file was generated by asn1tools version 0.145.2 Sun Jan 20 10:31:38 2019.

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Error {
    BadChoice,
    BadEnum,
    BadLength,
    OutOfData,
    OutOfMemory
}

struct Encoder<'a> {
    buf: &'a mut [u8],
    size: usize,
    pos: usize,
    error: Option<Error>
}

struct Decoder<'a> {
    buf: &'a[u8],
    size: usize,
    pos: usize,
    error: Option<Error>
}

impl<'a> Encoder<'a> {
    fn new(dst: &'a mut [u8]) -> Encoder {
        Encoder {
            size: 8 * dst.len(),
            buf: dst,
            pos: 0,
            error: None
        }
    }

    fn get_result(&self) -> Result<usize, Error> {
        if self.error.is_none() {
            return Ok((self.pos + 7) / 8);
        } else {
            return Err(self.error.unwrap());
        }
    }

    fn abort(&mut self, error: Error) {
        if self.error.is_none() {
            self.error = Some(error);
        }
    }

    fn alloc(&mut self, size: usize) -> Result<usize, ()> {
        if self.pos + size <= self.size {
            let pos = self.pos;
            self.pos += size;
            Ok(pos)
        } else {
            self.abort(Error::OutOfMemory);
            Err(())
        }
    }

    fn append_bit(&mut self, value: u8) {
        if let Ok(pos) = self.alloc(1) {
            if pos % 8 == 0 {
                self.buf[pos / 8] = 0;
            }

            self.buf[pos / 8] |= value << (7 - (pos % 8));
        }
    }

    fn append_bytes(&mut self, buf: &[u8]) {
        if let Ok(pos) = self.alloc(8 * buf.len()) {
            let byte_pos = pos / 8;
            let pos_in_byte = pos % 8;

            if pos_in_byte == 0 {
                self.buf.get_mut(byte_pos..byte_pos + buf.len())
                    .unwrap()
                    .copy_from_slice(buf.get(0..buf.len()).unwrap());
            } else {
                for i in 0..buf.len() {
                    self.buf[byte_pos + i] |= buf[i] >> pos_in_byte;
                    self.buf[byte_pos + i + 1] = buf[i] << (8 - pos_in_byte);
                }
            }
        }
    }

    fn append_u8(&mut self, value: u8) {
        self.append_bytes(&value.to_be_bytes());
    }

    fn append_u16(&mut self, value: u16) {
        self.append_bytes(&value.to_be_bytes());
    }

    fn append_u32(&mut self, value: u32) {
        self.append_bytes(&value.to_be_bytes());
    }

    fn append_u64(&mut self, value: u64) {
        self.append_bytes(&value.to_be_bytes());
    }

    fn append_i8(&mut self, value: i8) {
        self.append_u8((value as u8).wrapping_add(128));
    }

    fn append_i16(&mut self, value: i16) {
        self.append_u16((value as u16).wrapping_add(32768));
    }

    fn append_i32(&mut self, value: i32) {
        self.append_u32((value as u32).wrapping_add(2147483648));
    }

    fn append_i64(&mut self, value: i64) {
        self.append_u64((value as u64).wrapping_add(9223372036854775808));
    }

    fn append_bool(&mut self, value: bool) {
        self.append_bit(value as u8);
    }

    fn append_non_negative_binary_integer(&mut self, value: u64, size: usize) {
        for i in 0..size {
            self.append_bit((value >> (size - i - 1)) as u8 & 1);
        }
    }
}

impl<'a> Decoder<'a> {
    fn new(src: &'a[u8]) -> Decoder {
        Decoder {
            buf: src,
            size: 8 * src.len(),
            pos: 0,
            error: None
        }
    }

    fn get_result(&self) -> Result<usize, Error> {
        if self.error.is_none() {
            Ok((self.pos + 7) / 8)
        } else {
            Err(self.error.unwrap())
        }
    }

    fn abort(&mut self, error: Error) {
        if self.error.is_none() {
            self.error = Some(error);
        }
    }

    fn free(&mut self, size: usize) -> Result<usize, ()> {
        if self.pos + size <= self.size {
            let pos = self.pos;
            self.pos += size;
            Ok(pos)
        } else {
            self.abort(Error::OutOfData);
            Err(())
        }
    }

    fn read_bit(&mut self) -> u8 {
        if let Ok(pos) = self.free(1) {
            (self.buf[pos / 8] >> (7 - (pos % 8))) & 1
        } else {
            0
        }
    }

    fn read_bytes(&mut self, buf: &mut [u8]) {
        if let Ok(pos) = self.free(8 * buf.len()) {
            let byte_pos = pos / 8;
            let pos_in_byte = pos % 8;

            if pos_in_byte == 0 {
                buf.copy_from_slice(
                    self.buf.get(byte_pos..byte_pos + buf.len()).unwrap());
            } else {
                for i in 0..buf.len() {
                    buf[i] = self.buf[byte_pos + i] << pos_in_byte;
                    buf[i] |= self.buf[byte_pos + i + 1] >> (8 - pos_in_byte);
                }
            }
        }
    }

    fn read_u8(&mut self) -> u8 {
        let mut buf = [0; 1];

        self.read_bytes(&mut buf);

        u8::from_be_bytes(buf)
    }

    fn read_u16(&mut self) -> u16 {
        let mut buf = [0; 2];

        self.read_bytes(&mut buf);

        u16::from_be_bytes(buf)
    }

    fn read_u32(&mut self) -> u32 {
        let mut buf = [0; 4];

        self.read_bytes(&mut buf);

        u32::from_be_bytes(buf)
    }

    fn read_u64(&mut self) -> u64 {
        let mut buf = [0; 8];

        self.read_bytes(&mut buf);

        u64::from_be_bytes(buf)
    }

    fn read_i8(&mut self) -> i8 {
        self.read_u8().wrapping_sub(128) as i8
    }

    fn read_i16(&mut self) -> i16 {
        self.read_u16().wrapping_sub(32768) as i16
    }

    fn read_i32(&mut self) -> i32 {
        self.read_u32().wrapping_sub(2147483648) as i32
    }

    fn read_i64(&mut self) -> i64 {
        self.read_u64().wrapping_sub(9223372036854775808) as i64
    }

    fn read_bool(&mut self) -> bool {
        self.read_bit() != 0
    }

    fn read_non_negative_binary_integer(&mut self, size: usize) -> u64 {
        let mut value: u64 = 0;

        for _ in 0..size {
            value <<= 1;
            value |= self.read_bit() as u64;
        }

        value
    }
}

/// Type A in module RustSource.
#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceAJ {
    pub buf: [u8; 11]
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceA {
    pub a: i8,
    pub b: i16,
    pub c: i32,
    pub d: i64,
    pub e: u8,
    pub f: u16,
    pub g: u32,
    pub h: u64,
    pub i: bool,
    pub j: RustSourceAJ
}

impl RustSourceA {
    pub fn encode(&mut self, mut dst: &mut [u8]) -> Result<usize, Error> {
        let mut encoder = Encoder::new(&mut dst);

        self.encode_inner(&mut encoder);

        encoder.get_result()
    }

    pub fn decode(&mut self, src: &[u8]) -> Result<usize, Error> {
        let mut decoder = Decoder::new(&src);

        self.decode_inner(&mut decoder);

        decoder.get_result()
    }

    fn encode_inner(&mut self, encoder: &mut Encoder) {
        encoder.append_i8(self.a);
        encoder.append_i16(self.b);
        encoder.append_i32(self.c);
        encoder.append_i64(self.d);
        encoder.append_u8(self.e);
        encoder.append_u16(self.f);
        encoder.append_u32(self.g);
        encoder.append_u64(self.h);
        encoder.append_bool(self.i);
        encoder.append_bytes(&self.j.buf);
    }

    fn decode_inner(&mut self, decoder: &mut Decoder) {
        self.a = decoder.read_i8();
        self.b = decoder.read_i16();
        self.c = decoder.read_i32();
        self.d = decoder.read_i64();
        self.e = decoder.read_u8();
        self.f = decoder.read_u16();
        self.g = decoder.read_u32();
        self.h = decoder.read_u64();
        self.i = decoder.read_bool();
        decoder.read_bytes(&mut self.j.buf);
    }
}

/// Type AB in module RustSource.
#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceAB {
    pub a: i8,
    pub b: u16
}

impl RustSourceAB {
    pub fn encode(&mut self, mut dst: &mut [u8]) -> Result<usize, Error> {
        let mut encoder = Encoder::new(&mut dst);

        self.encode_inner(&mut encoder);

        encoder.get_result()
    }

    pub fn decode(&mut self, src: &[u8]) -> Result<usize, Error> {
        let mut decoder = Decoder::new(&src);

        self.decode_inner(&mut decoder);

        decoder.get_result()
    }

    fn encode_inner(&mut self, encoder: &mut Encoder) {
        encoder.append_non_negative_binary_integer(
            (self.a - -1) as u64,
            1);
        encoder.append_non_negative_binary_integer(
            (self.b - 10000) as u64,
            10);
    }

    fn decode_inner(&mut self, decoder: &mut Decoder) {
        self.a = decoder.read_non_negative_binary_integer(1) as i8;
        self.a += -1;
        self.b = decoder.read_non_negative_binary_integer(10) as u16;
        self.b += 10000;
    }
}

/// Type D in module RustSource.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum RustSourceDElemGH {
    I,
    J,
    K
}

impl Default for RustSourceDElemGH {
    fn default() -> Self {
        RustSourceDElemGH::I
    }
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum RustSourceDElemAB {
    C(u8),
    D(bool)
}

impl Default for RustSourceDElemAB {
    fn default() -> Self {
        RustSourceDElemAB::C(u8::default())
    }
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElemAE {
    pub length: u8
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElemA {
    pub b: RustSourceDElemAB,
    pub e: RustSourceDElemAE
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElemGL {
    pub length: u8,
    pub buf: [u8; 2]
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElemG {
    pub h: RustSourceDElemGH,
    pub l: RustSourceDElemGL
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElemMPQ {
    pub buf: [u8; 5]
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElemMP {
    pub q: RustSourceDElemMPQ,
    pub is_r_present: bool,
    pub r: bool
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElemM {
    pub is_n_present: bool,
    pub n: bool,
    pub o: i8,
    pub is_p_present: bool,
    pub p: RustSourceDElemMP
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceDElem {
    pub a: RustSourceDElemA,
    pub g: RustSourceDElemG,
    pub m: RustSourceDElemM
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceD {
    pub length: u8,
    pub elements: [RustSourceDElem; 10]
}

impl RustSourceD {
    pub fn encode(&mut self, mut dst: &mut [u8]) -> Result<usize, Error> {
        let mut encoder = Encoder::new(&mut dst);

        self.encode_inner(&mut encoder);

        encoder.get_result()
    }

    pub fn decode(&mut self, src: &[u8]) -> Result<usize, Error> {
        let mut decoder = Decoder::new(&src);

        self.decode_inner(&mut decoder);

        decoder.get_result()
    }

    fn encode_inner(&mut self, encoder: &mut Encoder) {
        encoder.append_non_negative_binary_integer(
            self.length as u64 - 1,
            4);

        for i in 0..self.length as usize {
            match self.elements[i].a.b {
                RustSourceDElemAB::C(value) => {
                    encoder.append_non_negative_binary_integer(0, 1);
                    encoder.append_non_negative_binary_integer(
                        value as u64 - 0,
                        1);
                },
                RustSourceDElemAB::D(value) => {
                    encoder.append_non_negative_binary_integer(1, 1);
                    encoder.append_bool(value);
                }
            }

            encoder.append_non_negative_binary_integer(
                self.elements[i].a.e.length as u64 - 3,
                1);
            encoder.append_non_negative_binary_integer(
                self.elements[i].g.h as u64,
                2);
            encoder.append_non_negative_binary_integer(
                self.elements[i].g.l.length as u64 - 1,
                1);
            encoder.append_bytes(
                &mut self.elements[i].g.l.buf[0..self.elements[i].g.l.length as usize]);
            encoder.append_bool(self.elements[i].m.is_n_present);
            encoder.append_bool(self.elements[i].m.o != 3);
            encoder.append_bool(self.elements[i].m.is_p_present);

            if self.elements[i].m.is_n_present {
                encoder.append_bool(self.elements[i].m.n);
            }

            if self.elements[i].m.o != 3 {
                encoder.append_non_negative_binary_integer(
                    (self.elements[i].m.o - -2) as u64,
                    3);
            }

            if self.elements[i].m.is_p_present {
                encoder.append_bool(self.elements[i].m.p.is_r_present);
                encoder.append_bytes(&self.elements[i].m.p.q.buf);

                if self.elements[i].m.p.is_r_present {
                    encoder.append_bool(self.elements[i].m.p.r);
                }
            }
        }
    }

    fn decode_inner(&mut self, decoder: &mut Decoder) {
        self.length = decoder.read_non_negative_binary_integer(4) as u8;
        self.length += 1;

        if self.length > 10 {
            decoder.abort(Error::BadLength);

            return;
        }

        for i in 0..self.length as usize {
            match decoder.read_non_negative_binary_integer(1) {
                0 => {
                    self.elements[i].a.b =
                        RustSourceDElemAB::C(decoder.read_non_negative_binary_integer(1) as u8 + 0);
                },
                1 => {
                    self.elements[i].a.b = RustSourceDElemAB::D(decoder.read_bool());
                },
                _ => {
                    decoder.abort(Error::BadChoice);

                    return;
                }
            }

            self.elements[i].a.e.length =
                decoder.read_non_negative_binary_integer(1) as u8;
            self.elements[i].a.e.length += 3;
            self.elements[i].g.h =
                match decoder.read_non_negative_binary_integer(2) {
                    0 => RustSourceDElemGH::I,
                    1 => RustSourceDElemGH::J,
                    2 => RustSourceDElemGH::K,
                    _ => {
                        decoder.abort(Error::BadEnum);

                        return;
                    }
                };
            self.elements[i].g.l.length =
                decoder.read_non_negative_binary_integer(1) as u8;
            self.elements[i].g.l.length += 1;
            decoder.read_bytes(
                &mut self.elements[i].g.l.buf[0..self.elements[i].g.l.length as usize]);
            self.elements[i].m.is_n_present = decoder.read_bool();
            let is_present = decoder.read_bool();
            self.elements[i].m.is_p_present = decoder.read_bool();

            if self.elements[i].m.is_n_present {
                self.elements[i].m.n = decoder.read_bool();
            }

            if is_present {
                self.elements[i].m.o =
                    decoder.read_non_negative_binary_integer(3) as i8;
                self.elements[i].m.o += -2;
            } else {
                self.elements[i].m.o = 3;
            }

            if self.elements[i].m.is_p_present {
                self.elements[i].m.p.is_r_present = decoder.read_bool();
                decoder.read_bytes(
                    &mut self.elements[i].m.p.q.buf);

                if self.elements[i].m.p.is_r_present {
                    self.elements[i].m.p.r = decoder.read_bool();
                }
            }
        }
    }
}

/// Type B in module RustSource.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum RustSourceB {
    A(i8),
    B(RustSourceA),
    C
}

impl Default for RustSourceB {
    fn default() -> Self {
        RustSourceB::A(i8::default())
    }
}

impl RustSourceB {
    pub fn encode(&mut self, mut dst: &mut [u8]) -> Result<usize, Error> {
        let mut encoder = Encoder::new(&mut dst);

        self.encode_inner(&mut encoder);

        encoder.get_result()
    }

    pub fn decode(&mut self, src: &[u8]) -> Result<usize, Error> {
        let mut decoder = Decoder::new(&src);

        self.decode_inner(&mut decoder);

        decoder.get_result()
    }

    fn encode_inner(&mut self, encoder: &mut Encoder) {
        match self {
            RustSourceB::A(value) => {
                encoder.append_non_negative_binary_integer(0, 2);
                encoder.append_i8(*value);
            },
            RustSourceB::B(value) => {
                encoder.append_non_negative_binary_integer(1, 2);
                value.encode_inner(encoder);
            },
            RustSourceB::C => {
                encoder.append_non_negative_binary_integer(2, 2);
            }
        }
    }

    fn decode_inner(&mut self, decoder: &mut Decoder) {
        match decoder.read_non_negative_binary_integer(2) {
            0 => {
                *self = RustSourceB::A(decoder.read_i8());
            },
            1 => {
                *self = RustSourceB::B(Default::default());

                if let RustSourceB::B(ref mut a) = self {
                    a.decode_inner(decoder);
                }
            },
            2 => {
                *self = RustSourceB::C;
            }
            _ => {
                decoder.abort(Error::BadChoice);

                return;
            }
        }
    }
}

/// Type E in module RustSource.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum RustSourceEAB {
    C(bool)
}

impl Default for RustSourceEAB {
    fn default() -> Self {
        RustSourceEAB::C(bool::default())
    }
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum RustSourceEA {
    B(RustSourceEAB)
}

impl Default for RustSourceEA {
    fn default() -> Self {
        RustSourceEA::B(RustSourceEAB::default())
    }
}

#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct RustSourceE {
    pub a: RustSourceEA
}

impl RustSourceE {
    pub fn encode(&mut self, mut dst: &mut [u8]) -> Result<usize, Error> {
        let mut encoder = Encoder::new(&mut dst);

        self.encode_inner(&mut encoder);

        encoder.get_result()
    }

    pub fn decode(&mut self, src: &[u8]) -> Result<usize, Error> {
        let mut decoder = Decoder::new(&src);

        self.decode_inner(&mut decoder);

        decoder.get_result()
    }

    fn encode_inner(&mut self, encoder: &mut Encoder) {
        match self.a {
            RustSourceEA::B(value) => {
                encoder.append_non_negative_binary_integer(0, 0);

                match value {
                    RustSourceEAB::C(value_2) => {
                        encoder.append_non_negative_binary_integer(0, 0);
                        encoder.append_bool(value_2);
                    }
                }
            }
        }
    }

    fn decode_inner(&mut self, decoder: &mut Decoder) {
        match decoder.read_non_negative_binary_integer(0) {
            0 => {
                let RustSourceEA::B(ref mut b) = self.a;

                match decoder.read_non_negative_binary_integer(0) {
                    0 => {
                        *b = RustSourceEAB::C(decoder.read_bool());
                    },
                    _ => {
                        decoder.abort(Error::BadChoice);

                        return;
                    }
                }
            },
            _ => {
                decoder.abort(Error::BadChoice);

                return;
            }
        }
    }
}
