<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use std::f32::NAN;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let (raw, offset) = {
      if let Some(raw) = self.tiff.find_first_ifd(Tag::Cr2Id) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(raw) = self.tiff.find_first_ifd(Tag::CFAPattern) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(off) = self.tiff.find_entry(Tag::Cr2OldOffset) {
        (&self.tiff, off.get_usize(0))
      } else {
        return Err("CR2: Couldn't find raw info".to_string())
      }
    };
    let src = &self.buffer[offset..];

    let (width, height, cpp, image) = {
      let decompressor = try!(LjpegDecompressor::new(src));
      let mut width = decompressor.width();
      let mut height = decompressor.height();
      let cpp = if decompressor.super_h() == 2 {3} else {1};
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Linearize the output (applies only to D2000 as far as I can tell)
      if camera.find_hint("linearization") {
        let table = {
          let linearization = fetch_tag!(self.tiff, Tag::GrayResponse);
          let mut t = [0 as u16;4096];
          for i in 0..t.len() {
            t[i] = linearization.get_u32(i) as u16;
          }
          LookupTable::new(&t)
        };

        let mut random = ljpegout[0] as u32;
        for o in ljpegout.chunks_mut(1) {
          o[0] = table.dither(o[0], &mut random);
        }
      }

      // Convert the YUV in sRAWs to RGB
      if cpp == 3 {
        try!(self.convert_to_rgb(camera, &mut ljpegout));
      }

      if raw.has_entry(Tag::ImageWidth) {
        width = fetch_tag!(raw, Tag::ImageWidth).get_usize(0) * cpp;
        height = fetch_tag!(raw, Tag::ImageLength).get_usize(0) ;
      } else if width/cpp < height {
        let temp = width/cpp;
        width = height*cpp;
        height = temp;
      } else if camera.find_hint("double_line") {
        width /= 2;
        height *= 2;
      }

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't
      //        been able to do it without hairy code
      if let Some(canoncol) = raw.find_entry(Tag::Cr2StripeWidths) {
        if canoncol.get_usize(0) == 0 {
          (width, height, cpp, ljpegout)
        } else {
          let mut out = vec![0 as u16; width*height];
          let mut fieldwidths = Vec::new();
          for _ in 0..canoncol.get_usize(0) {
            fieldwidths.push(canoncol.get_usize(1));
          }
          fieldwidths.push(canoncol.get_usize(2));

          if decompressor.super_v() == 2 {
            // We've decoded 2 lines at a time so we also need to copy two strips at a time
            let nfields = fieldwidths.len();
            let fieldwidth = fieldwidths[0];
            let mut fieldstart = 0;
            let mut inpos = 0;
            for _ in 0..nfields {
              let mut row = 0;
              while row < height {
                for _ in 0..nfields {
                  let outpos = row*width+fieldstart;
                  {
                    let outb = &mut out[outpos..outpos+fieldwidth];
                    let inb = &ljpegout[inpos..inpos+fieldwidth];
                    outb.copy_from_slice(inb);
                    row += 1;
                  }
                  let outpos = row*width+fieldstart;
                  let outb = &mut out[outpos..outpos+fieldwidth];
                  let inb = &ljpegout[inpos+width..inpos+width+fieldwidth];
                  outb.copy_from_slice(inb);
                  row += 1;
                  inpos += fieldwidth;
                }
                inpos += width; // skip the line we already used
              }
              fieldstart += fieldwidth;
            }
          } else {
            let sh = decompressor.super_h();
            let mut fieldstart = 0;
            let mut fieldpos = 0;
            for fieldwidth in fieldwidths {
              let fieldwidth = fieldwidth/sh*cpp;
              for row in 0..height {
                let outpos = row*width+fieldstart;
                let inpos = fieldpos+row*fieldwidth;
                let outb = &mut out[outpos..outpos+fieldwidth];
                let inb = &ljpegout[inpos..inpos+fieldwidth];
                outb.copy_from_slice(inb);
              }
              fieldstart += fieldwidth;
              fieldpos += fieldwidth*height;
            }
          }

          (width, height, cpp, out)
        }
      } else {
        (width, height, cpp, ljpegout)
      }
    };

    let mut img = Image::new(camera, width, height, try!(self.get_wb(camera)), image);
    if cpp == 3 {
      img.cpp = 3;
      img.width /= 3;
      img.crops = [0,0,0,0];
      img.blacklevels = [0,0,0,0];
      img.whitelevels = [65535,65535,65535,65535];
    }
    Ok(img)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self, cam: &Camera) -> Result<[f32;4], String> {
    if let Some(levels) = self.tiff.find_entry(Tag::Cr2ColorData) {
      let offset = if cam.wb_offset != 0 {cam.wb_offset} else {63};
      Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
          levels.get_force_u16(offset+3) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2PowerShotWB) {
      Ok([levels.get_force_u32(3) as f32, levels.get_force_u32(2) as f32,
          levels.get_force_u32(4) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2OldWB) {
      Ok([levels.get_f32(0), levels.get_f32(1), levels.get_f32(2), NAN])
    } else {
      // At least the D2000 has no WB
      Ok([NAN,NAN,NAN,NAN])
    }
  }

  fn convert_to_rgb(&self, cam: &Camera, image: &mut [u16]) -> Result<(),String>{
    let coeffs = try!(self.get_wb(cam));
    let c1 = (1024.0*1024.0/coeffs[0]) as i32;
    let c2 = coeffs[1] as i32;
    let c3 = (1024.0*1024.0/coeffs[2]) as i32;

    for pix in image.chunks_mut(3) {
      let y = pix[0] as i32;
      let cb = pix[1] as i32 - 16383;
      let cr = pix[2] as i32 - 16383;

      let r = c1 * (y + cr);
      let g = c2 * (y + ((-778*cb - (cr<<11)) >> 12));
      let b = c3 * (y + cb);

      pix[0] = clampbits(r >> 8, 16) as u16;
      pix[1] = clampbits(g >> 8, 16) as u16;
      pix[2] = clampbits(b >> 8, 16) as u16;
    }
    Ok(())
  }
}
<commit_msg>CR2: fix sraw rotation on dimension changed images<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use std::f32::NAN;
use itertools::Itertools;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let (raw, offset) = {
      if let Some(raw) = self.tiff.find_first_ifd(Tag::Cr2Id) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(raw) = self.tiff.find_first_ifd(Tag::CFAPattern) {
        (raw, fetch_tag!(raw, Tag::StripOffsets).get_usize(0))
      } else if let Some(off) = self.tiff.find_entry(Tag::Cr2OldOffset) {
        (&self.tiff, off.get_usize(0))
      } else {
        return Err("CR2: Couldn't find raw info".to_string())
      }
    };
    let src = &self.buffer[offset..];

    let (width, height, cpp, image) = {
      let decompressor = try!(LjpegDecompressor::new(src));
      let ljpegwidth = decompressor.width();
      let mut width = ljpegwidth;
      let mut height = decompressor.height();
      let cpp = if decompressor.super_h() == 2 {3} else {1};
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Linearize the output (applies only to D2000 as far as I can tell)
      if camera.find_hint("linearization") {
        let table = {
          let linearization = fetch_tag!(self.tiff, Tag::GrayResponse);
          let mut t = [0 as u16;4096];
          for i in 0..t.len() {
            t[i] = linearization.get_u32(i) as u16;
          }
          LookupTable::new(&t)
        };

        let mut random = ljpegout[0] as u32;
        for o in ljpegout.chunks_mut(1) {
          o[0] = table.dither(o[0], &mut random);
        }
      }

      // Convert the YUV in sRAWs to RGB
      if cpp == 3 {
        try!(self.convert_to_rgb(camera, &mut ljpegout));
      }

      if raw.has_entry(Tag::ImageWidth) {
        width = fetch_tag!(raw, Tag::ImageWidth).get_usize(0) * cpp;
        height = fetch_tag!(raw, Tag::ImageLength).get_usize(0) ;
      } else if width/cpp < height {
        let temp = width/cpp;
        width = height*cpp;
        height = temp;
      } else if camera.find_hint("double_line") {
        width /= 2;
        height *= 2;
      }

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't
      //        been able to do it without hairy code
      if let Some(canoncol) = raw.find_entry(Tag::Cr2StripeWidths) {
        if canoncol.get_usize(0) == 0 {
          (width, height, cpp, ljpegout)
        } else {
          let mut out = vec![0 as u16; width*height];
          let mut fieldwidths = Vec::new();
          for _ in 0..canoncol.get_usize(0) {
            fieldwidths.push(canoncol.get_usize(1));
          }
          fieldwidths.push(canoncol.get_usize(2));

          if decompressor.super_v() == 2 {
            // We've decoded 2 lines at a time so we also need to copy two strips at a time
            let nfields = fieldwidths.len();
            let fieldwidth = fieldwidths[0];
            let mut fieldstart = 0;
            let mut inpos = 0;
            for _ in 0..nfields {
              for row in (0..height).step(2) {
                for col in (0..fieldwidth).step(3) {
                  let outpos = row*width+fieldstart+col;
                  out[outpos..outpos+3].copy_from_slice(&ljpegout[inpos..inpos+3]);
                  let outpos = (row+1)*width+fieldstart+col;
                  let inpos2 = inpos+ljpegwidth;
                  out[outpos..outpos+3].copy_from_slice(&ljpegout[inpos2..inpos2+3]);
                  inpos += 3;
                  if inpos % ljpegwidth == 0 {
                    // we've used a full input line and we're reading 2 by 2 so skip one
                    inpos += ljpegwidth;
                  }
                }
              }
              fieldstart += fieldwidth;
            }
          } else {
            let sh = decompressor.super_h();
            let mut fieldstart = 0;
            let mut fieldpos = 0;
            for fieldwidth in fieldwidths {
              let fieldwidth = fieldwidth/sh*cpp;
              for row in 0..height {
                let outpos = row*width+fieldstart;
                let inpos = fieldpos+row*fieldwidth;
                let outb = &mut out[outpos..outpos+fieldwidth];
                let inb = &ljpegout[inpos..inpos+fieldwidth];
                outb.copy_from_slice(inb);
              }
              fieldstart += fieldwidth;
              fieldpos += fieldwidth*height;
            }
          }

          (width, height, cpp, out)
        }
      } else {
        (width, height, cpp, ljpegout)
      }
    };

    let mut img = Image::new(camera, width, height, try!(self.get_wb(camera)), image);
    if cpp == 3 {
      img.cpp = 3;
      img.width /= 3;
      img.crops = [0,0,0,0];
      img.blacklevels = [0,0,0,0];
      img.whitelevels = [65535,65535,65535,65535];
    }
    Ok(img)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self, cam: &Camera) -> Result<[f32;4], String> {
    if let Some(levels) = self.tiff.find_entry(Tag::Cr2ColorData) {
      let offset = if cam.wb_offset != 0 {cam.wb_offset} else {63};
      Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
          levels.get_force_u16(offset+3) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2PowerShotWB) {
      Ok([levels.get_force_u32(3) as f32, levels.get_force_u32(2) as f32,
          levels.get_force_u32(4) as f32, NAN])
    } else if let Some(levels) = self.tiff.find_entry(Tag::Cr2OldWB) {
      Ok([levels.get_f32(0), levels.get_f32(1), levels.get_f32(2), NAN])
    } else {
      // At least the D2000 has no WB
      Ok([NAN,NAN,NAN,NAN])
    }
  }

  fn convert_to_rgb(&self, cam: &Camera, image: &mut [u16]) -> Result<(),String>{
    let coeffs = try!(self.get_wb(cam));
    let c1 = (1024.0*1024.0/coeffs[0]) as i32;
    let c2 = coeffs[1] as i32;
    let c3 = (1024.0*1024.0/coeffs[2]) as i32;

    for pix in image.chunks_mut(3) {
      let y = pix[0] as i32;
      let cb = pix[1] as i32 - 16383;
      let cr = pix[2] as i32 - 16383;

      let r = c1 * (y + cr);
      let g = c2 * (y + ((-778*cb - (cr<<11)) >> 12));
      let b = c3 * (y + cb);

      pix[0] = clampbits(r >> 8, 16) as u16;
      pix[1] = clampbits(g >> 8, 16) as u16;
      pix[2] = clampbits(b >> 8, 16) as u16;
    }
    Ok(())
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

use heck::CamelCase;
use proc_macro::TokenStream;
use quote::{format_ident, quote, ToTokens};
use std::{
    cell::RefCell,
    collections::{BTreeSet, HashSet},
};

// CAUTION: This is all wildly unstable and relies on the compiler maintaining
// a certain order between proc macro expansions. So this could break any
// minute. Better have a robust CI.
thread_local! {
    static QUERIES: RefCell<Vec<String>> = Default::default();
}

pub(crate) fn mark_query(_args: TokenStream, input: TokenStream) -> TokenStream {
    // Parse the input.
    let input = syn::parse_macro_input!(input as syn::ItemFn);

    // Map everything to a string here. Compiler panics horribly if we hand out
    // the actual idents and generics.
    QUERIES.with(|c| c.borrow_mut().push(input.to_token_stream().to_string()));

    // Produce some output.
    let note = format!("call query via database: cx.{}(...)", input.sig.ident);
    let output = quote! {
        #[deprecated(note = #note)]
        #input
    };
    output.into()
}

pub(crate) fn derive_query_db(input: TokenStream) -> TokenStream {
    let input = proc_macro2::TokenStream::from(input);
    let mut output = proc_macro2::TokenStream::new();

    // Flush the accumulated queries.
    let queries = QUERIES.with(|c| std::mem::replace(&mut *c.borrow_mut(), Default::default()));

    // Make a set of conflicting argument names.
    let reserved: HashSet<_> = ["query_key", "query_storage", "query_tag", "query_result"]
        .iter()
        .copied()
        .collect();

    // Collect all query lifetimes.
    let mut ltset = BTreeSet::new();

    // Process the queries.
    let mut funcs = vec![];
    let mut caches = vec![];
    let mut tags = vec![];
    let mut tag_debugs = vec![];
    let mut keys = vec![];

    for raw_query in &queries {
        // Parse the fn.
        let query: syn::ItemFn = syn::parse_str(raw_query).unwrap();

        // Disect a few things.
        let name = query.sig.ident.clone();
        let mut generics = query.sig.generics.clone();
        let args = query.sig.inputs.iter().skip(1);
        let result = match query.sig.output {
            syn::ReturnType::Type(_, ty) => ty.as_ref().clone(),
            _ => panic!("query {} has no return type", name),
        };

        // Filter out the doc comments such that we can apply them to the trait
        // fn as well.
        let doc_attrs = query.attrs.iter().filter(|a| a.path.is_ident("doc"));

        // Determine the argument list of the query.
        let arg_pats = args.clone().map(|arg| match arg {
            syn::FnArg::Typed(pat) => pat,
            _ => unreachable!("there should be no self args left at this point"),
        });
        let arg_names: Vec<_> = arg_pats
            .clone()
            .enumerate()
            .map(|(i, pat)| match pat.pat.as_ref() {
                syn::Pat::Ident(id) if !reserved.contains(id.ident.to_string().as_str()) => {
                    id.ident.clone()
                }
                _ => format_ident!("arg{}", i),
            })
            .collect();
        let arg_types: Vec<_> = arg_pats
            .clone()
            .map(|pat| pat.ty.as_ref().clone())
            .collect();

        // Collect lifetimes and strip them from the generics.
        let original_generics = generics.clone();
        for param in std::mem::replace(&mut generics.params, Default::default()) {
            match param {
                syn::GenericParam::Lifetime(ltdef) => {
                    ltset.insert(ltdef.lifetime);
                }
                _ => generics.params.push(param),
            }
        }

        // Render the key type that we use to look up things in the database.
        let key_name = format_ident!("{}QueryKey", name.to_string().to_camel_case());
        let key_indices = (0..arg_types.len()).map(syn::Index::from);
        let doc = format!("The arguments passed to the `{}` query.", name);
        keys.push(quote! {
            #[doc = #doc]
            #[derive(Clone, PartialEq, Eq, Hash)]
            pub struct #key_name #original_generics (#(#arg_types),*);

            impl #original_generics std::fmt::Debug for #key_name #original_generics {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    f.debug_tuple("")#(.field(&self.#key_indices))*.finish()
                }
            }
        });

        // Determine the cache field name.
        let cache_name = format_ident!("cached_{}", name);

        // Render a query tag that can be pushed onto the query stack to break
        // cycles.
        let tag_name = format_ident!("{}", name.to_string().to_camel_case());
        let doc = format!("The `{}` query.", name);
        tags.push(quote! {
            #[doc = #doc]
            #tag_name (#key_name #original_generics),
        });
        tag_debugs.push(quote! {
            QueryTag::#tag_name (x) => write!(f, "{}{:?}", stringify!(#name), x),
        });

        // Render the query for the database trait.
        funcs.push(quote! {
            #(#doc_attrs)*
            fn #name #generics (&self, #(#arg_names: #arg_types),*) -> #result {
                let query_storage = self.storage();
                let query_key = #key_name(#(#arg_names),*);
                let query_tag = QueryTag::#tag_name(query_key.clone());

                // Check if we already have a result for this query.
                if let Some(result) = query_storage.#cache_name.borrow().get(&query_key) {
                    trace!("Serving {}{:?} from cache", stringify!(#name), query_key);
                    return result.clone();
                }
                trace!("Executing {}{:?}", stringify!(#name), query_key);

                // Push the query onto the stack, checking if it is already in
                // flight.
                query_storage.stack.borrow_mut().push(query_tag.clone());
                if !query_storage.inflight.borrow_mut().insert(query_tag.clone()) {
                    self.handle_cycle();
                    // The above never returns.
                }

                // Execute the query.
                #[allow(deprecated)]
                let query_result = #name(self.context(), #(#arg_names),*);
                query_storage.#cache_name.borrow_mut().insert(query_key, query_result.clone());

                // Pop the query from the stack.
                query_storage.inflight.borrow_mut().remove(&query_tag);
                query_storage.stack.borrow_mut().pop();
                query_result
            }
        });

        // Render the cache field for the storage struct.
        let doc = format!("Cached results of the `{}` query.", name);
        caches.push(quote! {
            #[doc = #doc]
            pub #cache_name: RefCell<HashMap<#key_name #original_generics, #result>>,
        });
    }

    // Extract query lifetimes.
    let lts = if ltset.is_empty() {
        quote! {}
    } else {
        let lts = ltset.iter();
        quote! { <#(#lts),*> }
    };

    // Generate the query database trait.
    output.extend(quote! {
        #input
        pub trait QueryDatabase #lts {
            /// The type passed as first argument to compiler query
            /// implementations.
            type Context: crate::Context #lts;

            /// Get the context that is passed to compiler query
            /// implementations.
            fn context(&self) -> &Self::Context;

            /// Get the query caches and runtime data.
            fn storage(&self) -> &QueryStorage #lts;

            /// Called when a query cycle is detected.
            fn handle_cycle(&self) -> ! {
                error!("Query cycle detected:");
                for x in self.storage().stack.borrow().iter() {
                    error!(" - {:?}", x);
                }
                panic!("query cycle detected");
            }

            #(#funcs)*
        }
    });

    // Generate the query storage struct.
    output.extend(quote! {
        /// A collection of query caches and runtime data for a `QueryDatabase`.
        #[derive(Default)]
        pub struct QueryStorage #lts {
            /// A stack of the currently-executing queries.
            pub stack: RefCell<Vec<QueryTag #lts>>,
            /// A set of the currently-executing queries.
            pub inflight: RefCell<HashSet<QueryTag #lts>>,

            #(#caches)*
        }
    });

    // Generate the query tag enum.
    output.extend(quote! {
        /// A tag identifying any of the queries in `QueryDatabase`.
        #[derive(Clone, Hash, Eq, PartialEq)]
        pub enum QueryTag #lts {
            #(#tags)*
        }

        impl #lts std::fmt::Debug for QueryTag #lts {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                match self {
                    #(#tag_debugs)*
                }
            }
        }
    });

    // Generate the query keys.
    output.extend(quote! {
        #(#keys)*
    });

    // Produce some output.
    // println!("{}", output);
    output.into()
}
<commit_msg>derive: Clone query key args, add before/after cb<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

use heck::CamelCase;
use proc_macro::TokenStream;
use quote::{format_ident, quote, ToTokens};
use std::{
    cell::RefCell,
    collections::{BTreeSet, HashSet},
};

// CAUTION: This is all wildly unstable and relies on the compiler maintaining
// a certain order between proc macro expansions. So this could break any
// minute. Better have a robust CI.
thread_local! {
    static QUERIES: RefCell<Vec<String>> = Default::default();
}

pub(crate) fn mark_query(_args: TokenStream, input: TokenStream) -> TokenStream {
    // Parse the input.
    let input = syn::parse_macro_input!(input as syn::ItemFn);

    // Map everything to a string here. Compiler panics horribly if we hand out
    // the actual idents and generics.
    QUERIES.with(|c| c.borrow_mut().push(input.to_token_stream().to_string()));

    // Produce some output.
    let note = format!("call query via database: cx.{}(...)", input.sig.ident);
    let output = quote! {
        #[deprecated(note = #note)]
        #input
    };
    output.into()
}

pub(crate) fn derive_query_db(input: TokenStream) -> TokenStream {
    let input = proc_macro2::TokenStream::from(input);
    let mut output = proc_macro2::TokenStream::new();

    // Flush the accumulated queries.
    let queries = QUERIES.with(|c| std::mem::replace(&mut *c.borrow_mut(), Default::default()));

    // Make a set of conflicting argument names.
    let reserved: HashSet<_> = ["query_key", "query_storage", "query_tag", "query_result"]
        .iter()
        .copied()
        .collect();

    // Collect all query lifetimes.
    let mut ltset = BTreeSet::new();

    // Process the queries.
    let mut funcs = vec![];
    let mut caches = vec![];
    let mut tags = vec![];
    let mut tag_debugs = vec![];
    let mut keys = vec![];

    for raw_query in &queries {
        // Parse the fn.
        let query: syn::ItemFn = syn::parse_str(raw_query).unwrap();

        // Disect a few things.
        let name = query.sig.ident.clone();
        let mut generics = query.sig.generics.clone();
        let args = query.sig.inputs.iter().skip(1);
        let result = match query.sig.output {
            syn::ReturnType::Type(_, ty) => ty.as_ref().clone(),
            _ => panic!("query {} has no return type", name),
        };

        // Filter out the doc comments such that we can apply them to the trait
        // fn as well.
        let doc_attrs = query.attrs.iter().filter(|a| a.path.is_ident("doc"));

        // Determine the argument list of the query.
        let arg_pats = args.clone().map(|arg| match arg {
            syn::FnArg::Typed(pat) => pat,
            _ => unreachable!("there should be no self args left at this point"),
        });
        let arg_names: Vec<_> = arg_pats
            .clone()
            .enumerate()
            .map(|(i, pat)| match pat.pat.as_ref() {
                syn::Pat::Ident(id) if !reserved.contains(id.ident.to_string().as_str()) => {
                    id.ident.clone()
                }
                _ => format_ident!("arg{}", i),
            })
            .collect();
        let arg_types: Vec<_> = arg_pats
            .clone()
            .map(|pat| pat.ty.as_ref().clone())
            .collect();

        // Collect lifetimes and strip them from the generics.
        let original_generics = generics.clone();
        for param in std::mem::replace(&mut generics.params, Default::default()) {
            match param {
                syn::GenericParam::Lifetime(ltdef) => {
                    ltset.insert(ltdef.lifetime);
                }
                _ => generics.params.push(param),
            }
        }

        // Render the key type that we use to look up things in the database.
        let key_name = format_ident!("{}QueryKey", name.to_string().to_camel_case());
        let key_indices = (0..arg_types.len()).map(syn::Index::from);
        let doc = format!("The arguments passed to the `{}` query.", name);
        keys.push(quote! {
            #[doc = #doc]
            #[derive(Clone, PartialEq, Eq, Hash)]
            pub struct #key_name #original_generics (#(#arg_types),*);

            impl #original_generics std::fmt::Debug for #key_name #original_generics {
                fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                    f.debug_tuple("")#(.field(&self.#key_indices))*.finish()
                }
            }
        });

        // Determine the cache field name.
        let cache_name = format_ident!("cached_{}", name);

        // Render a query tag that can be pushed onto the query stack to break
        // cycles.
        let tag_name = format_ident!("{}", name.to_string().to_camel_case());
        let doc = format!("The `{}` query.", name);
        tags.push(quote! {
            #[doc = #doc]
            #tag_name (#key_name #original_generics),
        });
        tag_debugs.push(quote! {
            QueryTag::#tag_name (x) => write!(f, "{}{:?}", stringify!(#name), x),
        });

        // Render the query for the database trait.
        funcs.push(quote! {
            #(#doc_attrs)*
            fn #name #generics (&self, #(#arg_names: #arg_types),*) -> #result {
                let query_storage = self.storage();
                let query_key = #key_name(#(Clone::clone(&#arg_names)),*);
                let query_tag = QueryTag::#tag_name(query_key.clone());
                self.before_query(&query_tag);

                // Check if we already have a result for this query.
                if let Some(result) = query_storage.#cache_name.borrow().get(&query_key) {
                    trace!("Serving {}{:?} from cache", stringify!(#name), query_key);
                    return result.clone();
                }
                trace!("Executing {}{:?}", stringify!(#name), query_key);

                // Push the query onto the stack, checking if it is already in
                // flight.
                query_storage.stack.borrow_mut().push(query_tag.clone());
                if !query_storage.inflight.borrow_mut().insert(query_tag.clone()) {
                    self.handle_cycle();
                    // The above never returns.
                }

                // Execute the query.
                #[allow(deprecated)]
                let query_result = #name(self.context(), #(#arg_names),*);
                query_storage.#cache_name.borrow_mut().insert(query_key, query_result.clone());

                // Pop the query from the stack.
                query_storage.inflight.borrow_mut().remove(&query_tag);
                query_storage.stack.borrow_mut().pop();
                self.after_query(&query_tag);
                query_result
            }
        });

        // Render the cache field for the storage struct.
        let doc = format!("Cached results of the `{}` query.", name);
        caches.push(quote! {
            #[doc = #doc]
            pub #cache_name: RefCell<HashMap<#key_name #original_generics, #result>>,
        });
    }

    // Extract query lifetimes.
    let lts = if ltset.is_empty() {
        quote! {}
    } else {
        let lts = ltset.iter();
        quote! { <#(#lts),*> }
    };

    // Generate the query database trait.
    output.extend(quote! {
        #input
        pub trait QueryDatabase #lts {
            /// The type passed as first argument to compiler query
            /// implementations.
            type Context: crate::Context #lts;

            /// Get the context that is passed to compiler query
            /// implementations.
            fn context(&self) -> &Self::Context;

            /// Get the query caches and runtime data.
            fn storage(&self) -> &QueryStorage #lts;

            /// Called when a query cycle is detected.
            fn handle_cycle(&self) -> ! {
                error!("Query cycle detected:");
                for x in self.storage().stack.borrow().iter() {
                    error!(" - {:?}", x);
                }
                panic!("query cycle detected");
            }

            /// Called before a query is executed.
            fn before_query(&self, tag: &QueryTag #lts) {}

            /// Called after a query is executed.
            fn after_query(&self, tag: &QueryTag #lts) {}

            #(#funcs)*
        }
    });

    // Generate the query storage struct.
    output.extend(quote! {
        /// A collection of query caches and runtime data for a `QueryDatabase`.
        #[derive(Default)]
        pub struct QueryStorage #lts {
            /// A stack of the currently-executing queries.
            pub stack: RefCell<Vec<QueryTag #lts>>,
            /// A set of the currently-executing queries.
            pub inflight: RefCell<HashSet<QueryTag #lts>>,

            #(#caches)*
        }
    });

    // Generate the query tag enum.
    output.extend(quote! {
        /// A tag identifying any of the queries in `QueryDatabase`.
        #[derive(Clone, Hash, Eq, PartialEq)]
        pub enum QueryTag #lts {
            #(#tags)*
        }

        impl #lts std::fmt::Debug for QueryTag #lts {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                match self {
                    #(#tag_debugs)*
                }
            }
        }
    });

    // Generate the query keys.
    output.extend(quote! {
        #(#keys)*
    });

    // Produce some output.
    // println!("{}", output);
    output.into()
}
<|endoftext|>


<commit_before>use super::memory::{self, address, Memory};
use super::memory::mappedmemory::MemoryToken;
use super::instruction::Instruction;

pub struct Emulator<'a, T, U>
    where T: Memory,
          U: Memory
{
    image_memory: MemoryToken<T>,
    bios_memory: MemoryToken<U>,
    controls_memory: memory::mappedmemory::MemoryToken<memory::SliceMemory>,
    pub memory: memory::MappedMemory<'a>,
    pub ip: usize,
    bios_mounted: bool,
}

impl<'a, T, U> Emulator<'a, T, U>
    where T: 'a + Memory,
          U: 'a + Memory
{
    pub fn new(img: T, bios: U) -> Emulator<'a, T, U> {
        let mut memory = memory::MappedMemory::new();
        let nm = MemoryToken::new(memory::NullMemory::new());
        memory.mount(0, &nm);

        let bios_memory = memory::mappedmemory::MemoryToken::new(bios);
        let image_memory = memory::mappedmemory::MemoryToken::new(img);
        memory.mount(0, &image_memory);
        memory.mount(address::BIOS_START_ADDRESS, &bios_memory);

        let controls_memory =
            MemoryToken::new(memory::SliceMemory::new(address::MAX_ADDRESS -
                                                      address::FLAGS_START_ADDRESS +
                                                      1));
        memory.mount(address::FLAGS_START_ADDRESS, &controls_memory);

        Emulator {
            memory: memory,
            image_memory: image_memory,
            bios_memory: bios_memory,
            ip: address::BIOS_START_ADDRESS,
            controls_memory: controls_memory,
            bios_mounted: true,
        }
    }

    pub fn flag_is_set(&self, flag_idx: usize) -> bool {
        let bit = flag_idx % 32;
        self.memory.get(address::FLAGS_START_ADDRESS + flag_idx / 32) & (1 << bit) != 0
    }

    pub fn get_register(&self, reg_idx: usize) -> u32 {
        self.memory.get(address::REGISTERS_START_ADDRESS + reg_idx * 4)
    }

    pub fn step(&mut self) {
        let instr = Instruction::from_memory(self.ip, &self.memory);
        instr.execute(&mut self.ip, &mut self.memory);

        self.check_bios_mount()
    }

    fn check_bios_mount(&mut self) {
        if self.flag_is_set(address::FLAG0_BIOS_DONE) && self.bios_mounted {
            self.memory.unmount(&self.bios_memory);
            self.bios_mounted = false;
        } else if !self.flag_is_set(address::FLAG0_BIOS_DONE) && !self.bios_mounted {
            self.memory.mount(address::BIOS_START_ADDRESS, &self.bios_memory);
            self.bios_mounted = true;
        }
    }

    pub fn is_halted(&self) -> bool {
        self.flag_is_set(address::FLAG0_HALTED)
    }
}

#[cfg(test)]
mod tests {
    use memory::{SliceMemory, NullMemory, address, Memory};

    #[test]
    fn unmounts_bios() {
        let bios = SliceMemory::from_slice(Box::new(
                                               [address::BIOS_START_ADDRESS as u32 + 16,
                                                 address::BIOS_START_ADDRESS as u32 + 20,
                                                 address::FLAGS_START_ADDRESS as u32,
                                                 0,

                                                 2,
                                                 0,
                                                 0,
                                                 0]));
        let mut emu = super::Emulator::new(NullMemory::new(), bios);

        assert!(!emu.flag_is_set(address::FLAG0_BIOS_DONE));
        assert_eq!(emu.memory.get(address::BIOS_START_ADDRESS + 16), 2);
        emu.step();
        assert!(emu.flag_is_set(address::FLAG0_BIOS_DONE));
        assert_eq!(emu.memory.get(address::BIOS_START_ADDRESS + 16), 0);
    }

    #[test]
    fn is_halted() {
        let bios = SliceMemory::from_slice(Box::new(
                                               [address::BIOS_START_ADDRESS as u32 + 16,
                                                 address::BIOS_START_ADDRESS as u32 + 20,
                                                 address::FLAGS_START_ADDRESS as u32,
                                                 0,

                                                 1,
                                                 0,
                                                 0,
                                                 0]));
        let mut emu = super::Emulator::new(NullMemory::new(), bios);

        assert!(!emu.is_halted());
        emu.step();
        assert!(emu.is_halted());
    }
}
<commit_msg>test(emulator): Test get_register<commit_after>use super::memory::{self, address, Memory};
use super::memory::mappedmemory::MemoryToken;
use super::instruction::Instruction;

pub struct Emulator<'a, T, U>
    where T: Memory,
          U: Memory
{
    image_memory: MemoryToken<T>,
    bios_memory: MemoryToken<U>,
    controls_memory: memory::mappedmemory::MemoryToken<memory::SliceMemory>,
    pub memory: memory::MappedMemory<'a>,
    pub ip: usize,
    bios_mounted: bool,
}

impl<'a, T, U> Emulator<'a, T, U>
    where T: 'a + Memory,
          U: 'a + Memory
{
    pub fn new(img: T, bios: U) -> Emulator<'a, T, U> {
        let mut memory = memory::MappedMemory::new();
        let nm = MemoryToken::new(memory::NullMemory::new());
        memory.mount(0, &nm);

        let bios_memory = memory::mappedmemory::MemoryToken::new(bios);
        let image_memory = memory::mappedmemory::MemoryToken::new(img);
        memory.mount(0, &image_memory);
        memory.mount(address::BIOS_START_ADDRESS, &bios_memory);

        let controls_memory =
            MemoryToken::new(memory::SliceMemory::new(address::MAX_ADDRESS -
                                                      address::FLAGS_START_ADDRESS +
                                                      1));
        memory.mount(address::FLAGS_START_ADDRESS, &controls_memory);

        Emulator {
            memory: memory,
            image_memory: image_memory,
            bios_memory: bios_memory,
            ip: address::BIOS_START_ADDRESS,
            controls_memory: controls_memory,
            bios_mounted: true,
        }
    }

    pub fn flag_is_set(&self, flag_idx: usize) -> bool {
        let bit = flag_idx % 32;
        self.memory.get(address::FLAGS_START_ADDRESS + flag_idx / 32) & (1 << bit) != 0
    }

    pub fn get_register(&self, reg_idx: usize) -> u32 {
        self.memory.get(address::REGISTERS_START_ADDRESS + reg_idx * 4)
    }

    pub fn step(&mut self) {
        let instr = Instruction::from_memory(self.ip, &self.memory);
        instr.execute(&mut self.ip, &mut self.memory);

        self.check_bios_mount()
    }

    fn check_bios_mount(&mut self) {
        if self.flag_is_set(address::FLAG0_BIOS_DONE) && self.bios_mounted {
            self.memory.unmount(&self.bios_memory);
            self.bios_mounted = false;
        } else if !self.flag_is_set(address::FLAG0_BIOS_DONE) && !self.bios_mounted {
            self.memory.mount(address::BIOS_START_ADDRESS, &self.bios_memory);
            self.bios_mounted = true;
        }
    }

    pub fn is_halted(&self) -> bool {
        self.flag_is_set(address::FLAG0_HALTED)
    }
}

#[cfg(test)]
mod tests {
    use memory::{SliceMemory, NullMemory, address, Memory};

    #[test]
    fn unmounts_bios() {
        let bios = SliceMemory::from_slice(Box::new(
                                               [address::BIOS_START_ADDRESS as u32 + 16,
                                                 address::BIOS_START_ADDRESS as u32 + 20,
                                                 address::FLAGS_START_ADDRESS as u32,
                                                 0,

                                                 2,
                                                 0,
                                                 0,
                                                 0]));
        let mut emu = super::Emulator::new(NullMemory::new(), bios);

        assert!(!emu.flag_is_set(address::FLAG0_BIOS_DONE));
        assert_eq!(emu.memory.get(address::BIOS_START_ADDRESS + 16), 2);
        emu.step();
        assert!(emu.flag_is_set(address::FLAG0_BIOS_DONE));
        assert_eq!(emu.memory.get(address::BIOS_START_ADDRESS + 16), 0);
    }

    #[test]
    fn is_halted() {
        let bios = SliceMemory::from_slice(Box::new(
                                               [address::BIOS_START_ADDRESS as u32 + 16,
                                                 address::BIOS_START_ADDRESS as u32 + 20,
                                                 address::FLAGS_START_ADDRESS as u32,
                                                 0,

                                                 1,
                                                 0,
                                                 0,
                                                 0]));
        let mut emu = super::Emulator::new(NullMemory::new(), bios);

        assert!(!emu.is_halted());
        emu.step();
        assert!(emu.is_halted());
    }

    #[test]
    fn get_register() {
        let mut emu = super::Emulator::new(NullMemory::new(), NullMemory::new());
        emu.memory.set(address::REGISTERS_START_ADDRESS + 1, 101);
        emu.memory.set(address::REGISTERS_START_ADDRESS, 100);
        assert_eq!(emu.get_register(1), 101);
        assert_eq!(emu.get_register(0), 100);
    }
}
<|endoftext|>


<commit_before>use mio;
use std::{
	io,
	os::raw::c_int,
	task::{
		Context,
		Poll,
	},
};
use tokio::io::PollEvented;

pub fn is_readable(fd: c_int) -> io::Result<bool> {
	let mut fds = libc::pollfd {
		fd,
		events: libc::POLLIN | libc::POLLHUP | libc::POLLERR,
		revents: 0,
	};
	loop {
		let r = unsafe { libc::poll(&mut fds, 1, 0) };
		if r == 0 {
			return Ok(false);
		}
		if r == 1 {
			return Ok(true);
		}
		let e = io::Error::last_os_error();
		if e.kind() == io::ErrorKind::Interrupted {
			continue;
		}
		return Ok(false);
	}
}

pub struct PollReadFd(PollEvented<EventedFd>);

impl PollReadFd {
	pub fn new(fd: c_int) -> io::Result<Self> {
		Ok(PollReadFd(PollEvented::new(EventedFd(fd))?))
	}

	pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
		if futures::ready!(self.0.poll_read_ready(cx, mio::Ready::readable()))?.is_readable() {
			Poll::Ready(Ok(()))
		} else {
			Poll::Pending
		}
	}

	pub fn clear_read_ready(&self, cx: &mut Context<'_>) -> io::Result<()> {
		self.0.clear_read_ready(cx, mio::Ready::readable())
	}
}

struct EventedFd(c_int);

impl mio::Evented for EventedFd {
	fn register(
		&self,
		poll: &mio::Poll,
		token: mio::Token,
		interest: mio::Ready,
		opts: mio::PollOpt,
	) -> io::Result<()> {
		let efd = mio::unix::EventedFd(&self.0);
		mio::Evented::register(&efd, poll, token, interest, opts)
	}

	fn reregister(
		&self,
		poll: &mio::Poll,
		token: mio::Token,
		interest: mio::Ready,
		opts: mio::PollOpt,
	) -> io::Result<()> {
		let efd = mio::unix::EventedFd(&self.0);
		mio::Evented::reregister(&efd, poll, token, interest, opts)
	}

	fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
		let efd = mio::unix::EventedFd(&self.0);
		mio::Evented::deregister(&efd, poll)
	}
}
<commit_msg>fix redundant import<commit_after>use std::{
	io,
	os::raw::c_int,
	task::{
		Context,
		Poll,
	},
};
use tokio::io::PollEvented;

pub fn is_readable(fd: c_int) -> io::Result<bool> {
	let mut fds = libc::pollfd {
		fd,
		events: libc::POLLIN | libc::POLLHUP | libc::POLLERR,
		revents: 0,
	};
	loop {
		let r = unsafe { libc::poll(&mut fds, 1, 0) };
		if r == 0 {
			return Ok(false);
		}
		if r == 1 {
			return Ok(true);
		}
		let e = io::Error::last_os_error();
		if e.kind() == io::ErrorKind::Interrupted {
			continue;
		}
		return Ok(false);
	}
}

pub struct PollReadFd(PollEvented<EventedFd>);

impl PollReadFd {
	pub fn new(fd: c_int) -> io::Result<Self> {
		Ok(PollReadFd(PollEvented::new(EventedFd(fd))?))
	}

	pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
		if futures::ready!(self.0.poll_read_ready(cx, mio::Ready::readable()))?.is_readable() {
			Poll::Ready(Ok(()))
		} else {
			Poll::Pending
		}
	}

	pub fn clear_read_ready(&self, cx: &mut Context<'_>) -> io::Result<()> {
		self.0.clear_read_ready(cx, mio::Ready::readable())
	}
}

struct EventedFd(c_int);

impl mio::Evented for EventedFd {
	fn register(
		&self,
		poll: &mio::Poll,
		token: mio::Token,
		interest: mio::Ready,
		opts: mio::PollOpt,
	) -> io::Result<()> {
		let efd = mio::unix::EventedFd(&self.0);
		mio::Evented::register(&efd, poll, token, interest, opts)
	}

	fn reregister(
		&self,
		poll: &mio::Poll,
		token: mio::Token,
		interest: mio::Ready,
		opts: mio::PollOpt,
	) -> io::Result<()> {
		let efd = mio::unix::EventedFd(&self.0);
		mio::Evented::reregister(&efd, poll, token, interest, opts)
	}

	fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
		let efd = mio::unix::EventedFd(&self.0);
		mio::Evented::deregister(&efd, poll)
	}
}
<|endoftext|>


<commit_before>//extern crate serde_json;
use rustc_serialize::json;

use std::error::Error;
use std::ffi::OsStr;
use std::fs;
use std::fs::File;
use std::io::{ self, BufReader, BufRead, Read };
use std::path::{ Path, PathBuf };
use std::str::FromStr;

use download;
use verify;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => return Err(format!("An error occured during package finding. {}", why)),
    });
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct Package {
    pub name: String,
    pub version: String,
    pub crc32: u32,
    pub url: String,
    pub dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    packages: Vec<Package>,
    version: i32
}

pub fn update_package_list(url: &str, path: &Path) -> Result<bool, String> {
    if (path.extension().is_some() &&
        path.extension().unwrap_or(OsStr::new("")) != ".json") ||
       (path.extension().is_none())
    {
        return Err(String::from(
            format!("Extension of package list is not .json: {}", path.to_str().unwrap_or("Invalid File"))
        ));
    }

    let mut path_temp = PathBuf::new();
    path_temp.push(path);
    path_temp.set_extension("json.tmp");

    if download::download_file(url, path_temp.as_path()).is_err() {
        return Err(String::from("Error occured while downloading package list"))
    }

    if verify::verify_file_crc32(&custom_try!(File::open(&path_temp))) ==
       verify::verify_file_crc32(&custom_try!(File::open(&path)))
    {
        fs::remove_file(path_temp);
        return Ok(false)
    } else {
        fs::remove_file(path);
        fs::rename(path_temp, path);
        return Ok(true)
    }
}

pub fn find_package(name: &str, path:&Path) -> Result<Vec<Package>, String> {
    let mut list = custom_try!(File::open(path));
    let mut reader = BufReader::new(list);
    let mut buffer = String::new();

    reader.read_to_string(&mut buffer);
    let package_list: PackageList = custom_try!(json::decode(&buffer));

    let filtered = package_list.packages
                    .into_iter()
                    .filter(|x| !x.name.contains(name))
                    .collect::<Vec<_>>();

    match filtered.len() {
        0 => Err(String::from("Package not found")),
        _ => Ok(filtered)
    }
}

pub fn download_and_find(name: &str, url:&str, path:&Path) -> Result<Vec<Package>, String>{
    if update_package_list(url, path).is_ok() {
        return find_package(name, path)
    } else {
        return Err(String::from("Error occured while downloading package list"))
    }
}

pub fn select_package(name: &str, path: &Path) -> Result<Package, String>{
    let found_packages = find_package(name, path)?;

    if found_packages.len() > 1 {
        for (i, package) in found_packages.iter().enumerate() {
            println!("Package {}: {}", i, package.name);
        }

        let mut input = String::new();
        custom_try!(io::stdin().read_line(&mut input));
        let input: u16 = custom_try!(input.trim().parse::<u16>());

        if input > found_packages.len() as u16 {
            return Err(String::from("Invalid input"))
        } else {
            return Ok(found_packages[input as usize].clone())
        }
    } else {
        return Ok(found_packages[0].clone())
    }
}<commit_msg>Change version type to u32<commit_after>//extern crate serde_json;
use rustc_serialize::json;

use std::error::Error;
use std::ffi::OsStr;
use std::fs;
use std::fs::File;
use std::io::{ self, BufReader, BufRead, Read };
use std::path::{ Path, PathBuf };
use std::str::FromStr;

use download;
use verify;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => return Err(format!("An error occured during package finding. {}", why)),
    });
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct Package {
    pub name: String,
    pub version: u32,
    pub crc32: u32,
    pub url: String,
    pub dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    packages: Vec<Package>,
    version: i32
}

pub fn update_package_list(url: &str, path: &Path) -> Result<bool, String> {
    if (path.extension().is_some() &&
        path.extension().unwrap_or(OsStr::new("")) != ".json") ||
       (path.extension().is_none())
    {
        return Err(String::from(
            format!("Extension of package list is not .json: {}", path.to_str().unwrap_or("Invalid File"))
        ));
    }

    let mut path_temp = PathBuf::new();
    path_temp.push(path);
    path_temp.set_extension("json.tmp");

    if download::download_file(url, path_temp.as_path()).is_err() {
        return Err(String::from("Error occured while downloading package list"))
    }

    if verify::verify_file_crc32(&custom_try!(File::open(&path_temp))) ==
       verify::verify_file_crc32(&custom_try!(File::open(&path)))
    {
        fs::remove_file(path_temp);
        return Ok(false)
    } else {
        fs::remove_file(path);
        fs::rename(path_temp, path);
        return Ok(true)
    }
}

pub fn find_package(name: &str, path:&Path) -> Result<Vec<Package>, String> {
    let mut list = custom_try!(File::open(path));
    let mut reader = BufReader::new(list);
    let mut buffer = String::new();

    reader.read_to_string(&mut buffer);
    let package_list: PackageList = custom_try!(json::decode(&buffer));

    let filtered = package_list.packages
                    .into_iter()
                    .filter(|x| !x.name.contains(name))
                    .collect::<Vec<_>>();

    match filtered.len() {
        0 => Err(String::from("Package not found")),
        _ => Ok(filtered)
    }
}

pub fn download_and_find(name: &str, url:&str, path:&Path) -> Result<Vec<Package>, String>{
    if update_package_list(url, path).is_ok() {
        return find_package(name, path)
    } else {
        return Err(String::from("Error occured while downloading package list"))
    }
}

pub fn select_package(name: &str, path: &Path) -> Result<Package, String>{
    let found_packages = find_package(name, path)?;

    if found_packages.len() > 1 {
        for (i, package) in found_packages.iter().enumerate() {
            println!("Package {}: {}", i, package.name);
        }

        let mut input = String::new();
        custom_try!(io::stdin().read_line(&mut input));
        let input: u16 = custom_try!(input.trim().parse::<u16>());

        if input > found_packages.len() as u16 {
            return Err(String::from("Invalid input"))
        } else {
            return Ok(found_packages[input as usize].clone())
        }
    } else {
        return Ok(found_packages[0].clone())
    }
}<|endoftext|>


<commit_before>use nom::{
  be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::Footer;

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<commit_msg>Add parser for channel assignment and sample size<commit_after>use nom::{
  be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment,
  Footer,
};

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<|endoftext|>


<commit_before>use crate::{
    api_call::{
        Kind::*,
        *,
    },
    application::*,
    user::*,
    version::USER_AGENT,
    ToParams,
};

use super::Parameters;

#[cfg(feature = "curl-types")]
pub mod curl;
#[cfg(feature = "http-types")]
mod http;
#[cfg(feature = "reqwest-types")]
mod reqwest;

#[derive(Clone, Debug)]
pub struct Request {
    pub method:     http_types::Method,
    pub path:       &'static str,
    pub parameters: Parameters,
    pub headers:    http_types::HeaderMap,
}

use http_types::Method;
use std::borrow::Cow;

impl Request {
    pub fn endpoint(kind: Kind,
                    application: Option<&Application>,
                    user: Option<&User>)
                    -> (Method, &'static str) {
        use super::endpoints::*;

        match (kind, application, user) {
            (Authorize, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, ..) => AUTHORIZE_ENDPOINT,
            (AuthRep, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, ..) => AUTHREP_ENDPOINT,
            (Report, ..) => REPORT_ENDPOINT,
        }
    }

    pub fn uri_and_body(&self) -> (Cow<str>, Option<&str>) {
        (self.parameters.path_and_query(self.path), self.parameters.body())
    }
}

pub trait FromRequest<P> {
    fn from_request(r: Request, params: P) -> Self;
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for Request {
    fn from(apicall: &ApiCall) -> Self {
        use http_types::{
            header::{
                HeaderName,
                HeaderValue,
            },
            HeaderMap,
        };

        let (method, path) = Request::endpoint(apicall.kind(), apicall.application(), apicall.user());

        let mut params = Vec::with_capacity(8);
        apicall.to_params(&mut params);

        let parameters = Parameters::new(&method, params.as_slice());

        let mut headers =
            apicall.extensions().map_or_else(|| HeaderMap::with_capacity(1),
                                             |e| {
                                                 let options = e.to_string();
                                                 let mut h = HeaderMap::with_capacity(2);
                                                 let val = HeaderValue::from_str(options.as_str());

                                                 if let Ok(val) = val {
                                                     h.insert(HeaderName::from_static("3scale-options"), val);
                                                 }

                                                 h
                                             });

        headers.insert("User-Agent", HeaderValue::from_static(USER_AGENT));

        Request { method,
                  path,
                  parameters,
                  headers }
    }
}
<commit_msg>http/request: redesign the trait to configure a client with a Request<commit_after>use crate::{
    api_call::{
        Kind::*,
        *,
    },
    application::*,
    user::*,
    version::USER_AGENT,
    ToParams,
};

use super::Parameters;

#[cfg(feature = "curl-types")]
pub mod curl;
#[cfg(feature = "http-types")]
mod http;
#[cfg(feature = "reqwest-types")]
mod reqwest;

#[derive(Clone, Debug)]
pub struct Request {
    pub method:     http_types::Method,
    pub path:       &'static str,
    pub parameters: Parameters,
    pub headers:    http_types::HeaderMap,
}

use http_types::Method;
use std::borrow::Cow;

impl Request {
    pub fn endpoint(kind: Kind,
                    application: Option<&Application>,
                    user: Option<&User>)
                    -> (Method, &'static str) {
        use super::endpoints::*;

        match (kind, application, user) {
            (Authorize, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, ..) => AUTHORIZE_ENDPOINT,
            (AuthRep, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, ..) => AUTHREP_ENDPOINT,
            (Report, ..) => REPORT_ENDPOINT,
        }
    }

    pub fn uri_and_body(&self) -> (Cow<str>, Option<&str>) {
        (self.parameters.path_and_query(self.path), self.parameters.body())
    }
}

/// This trait needs to be implemented by each client to set up a specific request.
///
/// The 'client lifetime will be useful if your Output return value needs to get hold of it. Such
/// is the case of curl's Easy client when sending POST requests via their Transfer<'client, 'data>
/// type, but for other clients which don't need to wrap the original client it's simply elided.
pub trait SetupRequest<'client, P, Output> {
    fn setup_request(&'client mut self, r: Request, params: P) -> Output;
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for Request {
    fn from(apicall: &ApiCall) -> Self {
        use http_types::{
            header::{
                HeaderName,
                HeaderValue,
            },
            HeaderMap,
        };

        let (method, path) = Request::endpoint(apicall.kind(), apicall.application(), apicall.user());

        let mut params = Vec::with_capacity(8);
        apicall.to_params(&mut params);

        let parameters = Parameters::new(&method, params.as_slice());

        let mut headers =
            apicall.extensions().map_or_else(|| HeaderMap::with_capacity(1),
                                             |e| {
                                                 let options = e.to_string();
                                                 let mut h = HeaderMap::with_capacity(2);
                                                 let val = HeaderValue::from_str(options.as_str());

                                                 if let Ok(val) = val {
                                                     h.insert(HeaderName::from_static("3scale-options"), val);
                                                 }

                                                 h
                                             });

        headers.insert("User-Agent", HeaderValue::from_static(USER_AGENT));

        Request { method,
                  path,
                  parameters,
                  headers }
    }
}
<|endoftext|>


<commit_before>//NOTE: apparently, when looking up statics by ID, they're offset by 0x4000.

use mul_reader;
use byte_helpers;

type pixel = u16;

trait Tile {
    fn with_transparency(&self, transparency_color: pixel) -> ~[pixel];
}

pub type MapTile = {
    header: u32,
    raw_image: ~[pixel]
};

impl MapTile : Tile {
    fn with_transparency(&self, transparency_color: pixel) -> ~[pixel] {
        let mut image: ~[pixel] = ~[];
        let data_source = byte_helpers::Buffer(copy self.raw_image);

        for uint::range(0, 44) |i| {

            let slice_size: uint = if (i >= 22) {(44 - i) * 2} else {(i + 1) * 2};
            image.grow((22 - (slice_size / 2)), &transparency_color);
            let slice_data = data_source.read(slice_size);
            image.push_all(slice_data);
            image.grow((22 - (slice_size / 2)), &transparency_color);
        };
        image
    }
}

pub type StaticTile = {
    data_size: u16,
    trigger: u16,
    width: u16,
    height: u16,
    raw_image: ~[pixel]
};

impl StaticTile : Tile {
    fn with_transparency(&self, transparency_color: pixel) -> ~[pixel] {
        let dummy: ~[pixel] = ~[];
        dummy
    }
}

pub struct TileReader {
    mul_reader: mul_reader::MulReader
}

impl TileReader {

    fn read_tile(id: uint) -> option::Option<MapTile> {
        match self.mul_reader.read(id) {
            option::Some(record) => {
                if (vec::len(record.data) != expected_tile_size) {
                    return option::None;
                }

                let data_source = byte_helpers::Buffer(copy record.data);
                let record_header = byte_helpers::bytes_to_le_uint(data_source.read(4));
                let raw_image: ~[pixel] = byte_helpers::u8vec_to_u16vec(data_source.read(44 * 44 * 2));

                option::Some({
                    header: record_header as u32,
                    raw_image: raw_image
                })
            },
            option::None => option::None
        }
    }

    fn read_static(id: uint) -> option::Option<StaticTile> {
        match self.mul_reader.read(id) {
            option::Some(record) => {
                let data_source = byte_helpers::Buffer(copy record.data);
                let data_size: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16; //Might not be size :P
                let trigger: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;
                let width: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;
                let height: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;

                if (width == 0 || height >= 1024 || height == 0 || height >= 1024) {
                    //io::println("Bad image dimensions found");
                    return option::None;
                }

                let mut image: ~[pixel] = data_source.read(data_source.length - 8);

                option::Some({
                    data_size: data_size,
                    trigger: trigger,
                    width: width,
                    height: height,
                    raw_image: image //FIXME
                })
            },
            option::None => option::None
        }
    }

    //Read the offset table
    /*let mut offset_table: ~[u16] = ~[];
    for uint::range(0, height as uint) |_index| {
        let offset = data_source.read_le_uint(2) as u16;
        offset_table.push(offset);
    }

    let data_start_pos = data_source.pos;

    for offset_table.each |offset| {
        data_source.seek(data_start_pos as uint + (*offset as uint * 2));
        let mut current_row_width: uint = 0;

        loop {
            let x_offset = data_source.read_le_uint(2) as u16;
            let run_length = data_source.read_le_uint(2) as u16;

            if (x_offset + run_length == 0) {
                image.grow(width as uint - current_row_width, &transparent);
                break;
            } else {
                let run = byte_helpers::u8vec_to_u16vec(data_source.read((run_length as uint) * 2));
                image.grow(x_offset as uint, &transparent);
                image.push_all(run);
                current_row_width += x_offset as uint + run_length as uint;
                assert(current_row_width <= width as uint);
            }
        }
    }

    return option::Some({
        data_size: data_size,
        trigger: trigger,
        width: width,
        height: height,
        image: image
    });
    }*/
}

pub fn TileReader(index_path: &path::Path, mul_path: &path::Path) -> result::Result<TileReader, ~str> {
    match mul_reader::MulReader(index_path, mul_path) {
        result::Err(message) => result::Err(message),
        result::Ok(mul_reader) => {
            result::Ok(TileReader{
                mul_reader: mul_reader
            })
        }
    }
}

const transparent: pixel = 0b1000000000000000;
const expected_tile_size: uint = 2048;

/*pub fn load_tiles(root_path: ~str) -> (~[(uint, MapTile)], ~[(uint, StaticTile)]) { //TODO: Find a better return type for this
    match mul_reader::reader(root_path, ~"artidx.mul", ~"art.mul") {
        result::Err(message) => {
            io::println(fmt!("Error reading art tiles - %s", message));
            fail
        },
        result::Ok(reader) => {
            let mut map_tiles: ~[(uint, MapTile)] = ~[];
            let mut static_tiles: ~[(uint, StaticTile)] = ~[];

            let mut index:uint = 0;
            while (reader.eof() != true) {
                let item: option::Option<mul_reader::MulRecord> = reader.read();
                if option::is_some(&item) {
                    let unwrapped: mul_reader::MulRecord = option::unwrap(item);
                    //let record_header = byte_helpers::bytes_to_le_uint(vec::slice(unwrapped.data, 0, 3));

                    if (index < 0x4000) {
                        let maybe_map_tile: option::Option<MapTile> = parse_map_tile(unwrapped);
                        if option::is_some(&maybe_map_tile) {
                            let tuple = (index, option::unwrap(maybe_map_tile));
                            map_tiles.push(tuple);
                        }
                    } else if (index < 0x8000){
                        let maybe_static_tile: option::Option<StaticTile> = parse_static_tile(unwrapped);
                        if option::is_some(&maybe_static_tile) {
                            let tuple = (index, option::unwrap(maybe_static_tile));
                            static_tiles.push(tuple);
                        }
                    }
                }
                index += 1;
            }

            (map_tiles, static_tiles)
        }
    }

}

fn parse_static_tile(record: mul_reader::MulRecord) -> option::Option<StaticTile> {

    let data_source = byte_helpers::ByteBuffer(copy record.data);

    let data_size: u16 = data_source.read_le_uint(2) as u16; //Might not be size :P
    let trigger: u16 = data_source.read_le_uint(2) as u16;
    let width: u16 = data_source.read_le_uint(2) as u16;
    let height: u16 = data_source.read_le_uint(2) as u16;

    if (width == 0 || height >= 1024 || height == 0 || height >= 1024) {
        io::println("Bad image dimensions found");
        return option::None;
    }

    let mut image: ~[u16] = ~[];

    //Read the offset table
    let mut offset_table: ~[u16] = ~[];
    for uint::range(0, height as uint) |_index| {
        let offset = data_source.read_le_uint(2) as u16;
        offset_table.push(offset);
    }

    let data_start_pos = data_source.pos;

    for offset_table.each |offset| {
        data_source.seek(data_start_pos as uint + (*offset as uint * 2));
        let mut current_row_width: uint = 0;

        loop {
            let x_offset = data_source.read_le_uint(2) as u16;
            let run_length = data_source.read_le_uint(2) as u16;

            if (x_offset + run_length == 0) {
                image.grow(width as uint - current_row_width, &transparent);
                break;
            } else {
                let run = byte_helpers::u8vec_to_u16vec(data_source.read((run_length as uint) * 2));
                image.grow(x_offset as uint, &transparent);
                image.push_all(run);
                current_row_width += x_offset as uint + run_length as uint;
                assert(current_row_width <= width as uint);
            }
        }
    }

    return option::Some({
        data_size: data_size,
        trigger: trigger,
        width: width,
        height: height,
        image: image
    });
}*/

/*
pub fn to_bitmap(width: u32, height: u32, data: ~[u16]) -> ~[u8] { //TODO: Make this take arbitrary pixel depths
    let signature: ~[u8] = ~[0x42, 0x4D];
    let file_size: ~[u8] = byte_helpers::uint_to_le_bytes(((width * height * 2) + 14 + 40) as u64, 4);
    let reserved: ~[u8] = ~[0, 0, 0, 0];
    let data_offset: ~[u8] = byte_helpers::uint_to_le_bytes(54, 4);

    let header_size: ~[u8] = byte_helpers::uint_to_le_bytes(40, 4);
    let width_bytes: ~[u8] = byte_helpers::uint_to_le_bytes(width as u64, 4); //FIXME: should be signed?
    let height_bytes: ~[u8] = byte_helpers::uint_to_le_bytes(height as u64, 4);
    let colour_panes: ~[u8] = ~[1, 0];
    let depth: ~[u8] = ~[16, 0];
    let compression: ~[u8] = ~[0,0,0,0];
    let image_size: ~[u8] = ~[0,0,0,0];
    let horizontal_res: ~[u8] = ~[0, 0, 0, 0];
    let vertical_res: ~[u8] = ~[0, 0, 0, 0];
    let palette_count: ~[u8] = ~[0, 0, 0, 0];
    let important_colours: ~[u8] = ~[0, 0, 0, 0];

    //54 bytes so far
    //TODO: explode the image vector, iterate backwards, turn it into bytes
    let mut rows: ~[~[u8]] = ~[];
    for uint::range(0, height as uint) |i| {
        let slice = vec::slice(data, i * (width as uint), (i+1) * (width as uint));
        let mut row: ~[u8] = ~[];
        for slice.each |sliced| {
            row.push_all(byte_helpers::uint_to_le_bytes(*sliced as u64, 2));
        }
        rows.push(row);
    };
    vec::reverse(rows);
    //vec::grow(pixels, 44 * 44 * 4, 0x7f);

    return vec::concat(~[
        signature,
        file_size,
        reserved,
        data_offset,

        header_size,
        width_bytes,
        height_bytes,
        colour_panes,
        depth,
        compression,
        image_size,
        horizontal_res,
        vertical_res,
        palette_count,
        important_colours,

        vec::concat(rows)
    ]);
}*/
<commit_msg>Static tile parsing<commit_after>//NOTE: apparently, when looking up statics by ID, they're offset by 0x4000.

use mul_reader;
use byte_helpers;

type pixel = u16;

trait Tile {
    fn with_transparency(&self, transparency_color: pixel) -> ~[pixel];
}

pub type MapTile = {
    header: u32,
    raw_image: ~[pixel]
};

impl MapTile : Tile {
    fn with_transparency(&self, transparency_color: pixel) -> ~[pixel] {
        let mut image: ~[pixel] = ~[];
        let data_source = byte_helpers::Buffer(copy self.raw_image);

        for uint::range(0, 44) |i| {

            let slice_size: uint = if (i >= 22) {(44 - i) * 2} else {(i + 1) * 2};
            image.grow((22 - (slice_size / 2)), &transparency_color);
            let slice_data = data_source.read(slice_size);
            image.push_all(slice_data);
            image.grow((22 - (slice_size / 2)), &transparency_color);
        };
        image
    }
}

pub type StaticTile = {
    data_size: u16,
    trigger: u16,
    width: u16,
    height: u16,
    raw_image_rows: ~[Row]
};

impl StaticTile : Tile {
    fn with_transparency(&self, transparency_color: pixel) -> ~[pixel] {
        let mut image: ~[pixel] = ~[];

        for self.raw_image_rows.each |row| {
            let mut current_width = 0;
            for row.each |run_pair| {
                image.grow(run_pair.offset as uint, &transparency_color);
                image.push_all(run_pair.run);
                current_width += run_pair.offset as uint + run_pair.run.len();
                assert current_width <= self.width as uint
            }
            if current_width < self.width as uint {
                image.grow((self.width as uint) - current_width, &transparency_color)
            }
        }
        image
    }
}

pub type RunPair = {
    offset: u16,
    run: ~[pixel]
};

pub type Row = ~[RunPair];

const expected_tile_size: uint = 2048;

pub struct TileReader {
    mul_reader: mul_reader::MulReader
}

impl TileReader {

    fn read_tile(id: uint) -> option::Option<MapTile> {
        match self.mul_reader.read(id) {
            option::Some(record) => {
                if (vec::len(record.data) != expected_tile_size) {
                    return option::None;
                }

                let data_source = byte_helpers::Buffer(copy record.data);
                let record_header = byte_helpers::bytes_to_le_uint(data_source.read(4));
                let raw_image: ~[pixel] = byte_helpers::u8vec_to_u16vec(data_source.read(44 * 44 * 2));

                option::Some({
                    header: record_header as u32,
                    raw_image: raw_image
                })
            },
            option::None => option::None
        }
    }

    fn read_static(id: uint) -> option::Option<StaticTile> {
        match self.mul_reader.read(id) {
            option::Some(record) => {
                let data_source = byte_helpers::Buffer(copy record.data);
                let data_size: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16; //Might not be size :P
                let trigger: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;
                let width: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;
                let height: u16 = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;

                if (width == 0 || height >= 1024 || height == 0 || height >= 1024) {
                    //io::println("Bad image dimensions found");
                    return option::None;
                }

                //Read the offset table
                let mut offset_table: ~[u16] = ~[];
                for uint::range(0, height as uint) |_index| {
                    let offset = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;
                    offset_table.push(offset);
                }

                let data_start_pos = data_source.pos;
                let mut rows = ~[];

                for offset_table.each |offset| {
                    data_source.seek(data_start_pos as uint + (*offset as uint * 2));
                    let mut current_row_width: uint = 0;
                    let mut row = ~[];

                    loop {
                        let x_offset = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;
                        let run_length = byte_helpers::bytes_to_le_uint(data_source.read(2)) as u16;

                        if (x_offset + run_length == 0) {
                            break;
                        } else {
                            row.push({
                                offset: x_offset,
                                run: byte_helpers::u8vec_to_u16vec(data_source.read((run_length as uint) * 2))
                            });
                            current_row_width += x_offset as uint + run_length as uint;
                            assert(current_row_width <= width as uint);
                        }
                    }
                    rows.push(row);
                }

                option::Some({
                    data_size: data_size,
                    trigger: trigger,
                    width: width,
                    height: height,
                    raw_image_rows: rows
                })
            },
            option::None => option::None
        }
    }
}

pub fn TileReader(index_path: &path::Path, mul_path: &path::Path) -> result::Result<TileReader, ~str> {
    match mul_reader::MulReader(index_path, mul_path) {
        result::Err(message) => result::Err(message),
        result::Ok(mul_reader) => {
            result::Ok(TileReader{
                mul_reader: mul_reader
            })
        }
    }
}

/*pub fn load_tiles(root_path: ~str) -> (~[(uint, MapTile)], ~[(uint, StaticTile)]) { //TODO: Find a better return type for this
    match mul_reader::reader(root_path, ~"artidx.mul", ~"art.mul") {
        result::Err(message) => {
            io::println(fmt!("Error reading art tiles - %s", message));
            fail
        },
        result::Ok(reader) => {
            let mut map_tiles: ~[(uint, MapTile)] = ~[];
            let mut static_tiles: ~[(uint, StaticTile)] = ~[];

            let mut index:uint = 0;
            while (reader.eof() != true) {
                let item: option::Option<mul_reader::MulRecord> = reader.read();
                if option::is_some(&item) {
                    let unwrapped: mul_reader::MulRecord = option::unwrap(item);
                    //let record_header = byte_helpers::bytes_to_le_uint(vec::slice(unwrapped.data, 0, 3));

                    if (index < 0x4000) {
                        let maybe_map_tile: option::Option<MapTile> = parse_map_tile(unwrapped);
                        if option::is_some(&maybe_map_tile) {
                            let tuple = (index, option::unwrap(maybe_map_tile));
                            map_tiles.push(tuple);
                        }
                    } else if (index < 0x8000){
                        let maybe_static_tile: option::Option<StaticTile> = parse_static_tile(unwrapped);
                        if option::is_some(&maybe_static_tile) {
                            let tuple = (index, option::unwrap(maybe_static_tile));
                            static_tiles.push(tuple);
                        }
                    }
                }
                index += 1;
            }

            (map_tiles, static_tiles)
        }
    }

}

fn parse_static_tile(record: mul_reader::MulRecord) -> option::Option<StaticTile> {

    let data_source = byte_helpers::ByteBuffer(copy record.data);

    let data_size: u16 = data_source.read_le_uint(2) as u16; //Might not be size :P
    let trigger: u16 = data_source.read_le_uint(2) as u16;
    let width: u16 = data_source.read_le_uint(2) as u16;
    let height: u16 = data_source.read_le_uint(2) as u16;

    if (width == 0 || height >= 1024 || height == 0 || height >= 1024) {
        io::println("Bad image dimensions found");
        return option::None;
    }

    let mut image: ~[u16] = ~[];

    //Read the offset table
    let mut offset_table: ~[u16] = ~[];
    for uint::range(0, height as uint) |_index| {
        let offset = data_source.read_le_uint(2) as u16;
        offset_table.push(offset);
    }

    let data_start_pos = data_source.pos;

    for offset_table.each |offset| {
        data_source.seek(data_start_pos as uint + (*offset as uint * 2));
        let mut current_row_width: uint = 0;

        loop {
            let x_offset = data_source.read_le_uint(2) as u16;
            let run_length = data_source.read_le_uint(2) as u16;

            if (x_offset + run_length == 0) {
                image.grow(width as uint - current_row_width, &transparent);
                break;
            } else {
                let run = byte_helpers::u8vec_to_u16vec(data_source.read((run_length as uint) * 2));
                image.grow(x_offset as uint, &transparent);
                image.push_all(run);
                current_row_width += x_offset as uint + run_length as uint;
                assert(current_row_width <= width as uint);
            }
        }
    }

    return option::Some({
        data_size: data_size,
        trigger: trigger,
        width: width,
        height: height,
        image: image
    });
}*/

/*
pub fn to_bitmap(width: u32, height: u32, data: ~[u16]) -> ~[u8] { //TODO: Make this take arbitrary pixel depths
    let signature: ~[u8] = ~[0x42, 0x4D];
    let file_size: ~[u8] = byte_helpers::uint_to_le_bytes(((width * height * 2) + 14 + 40) as u64, 4);
    let reserved: ~[u8] = ~[0, 0, 0, 0];
    let data_offset: ~[u8] = byte_helpers::uint_to_le_bytes(54, 4);

    let header_size: ~[u8] = byte_helpers::uint_to_le_bytes(40, 4);
    let width_bytes: ~[u8] = byte_helpers::uint_to_le_bytes(width as u64, 4); //FIXME: should be signed?
    let height_bytes: ~[u8] = byte_helpers::uint_to_le_bytes(height as u64, 4);
    let colour_panes: ~[u8] = ~[1, 0];
    let depth: ~[u8] = ~[16, 0];
    let compression: ~[u8] = ~[0,0,0,0];
    let image_size: ~[u8] = ~[0,0,0,0];
    let horizontal_res: ~[u8] = ~[0, 0, 0, 0];
    let vertical_res: ~[u8] = ~[0, 0, 0, 0];
    let palette_count: ~[u8] = ~[0, 0, 0, 0];
    let important_colours: ~[u8] = ~[0, 0, 0, 0];

    //54 bytes so far
    //TODO: explode the image vector, iterate backwards, turn it into bytes
    let mut rows: ~[~[u8]] = ~[];
    for uint::range(0, height as uint) |i| {
        let slice = vec::slice(data, i * (width as uint), (i+1) * (width as uint));
        let mut row: ~[u8] = ~[];
        for slice.each |sliced| {
            row.push_all(byte_helpers::uint_to_le_bytes(*sliced as u64, 2));
        }
        rows.push(row);
    };
    vec::reverse(rows);
    //vec::grow(pixels, 44 * 44 * 4, 0x7f);

    return vec::concat(~[
        signature,
        file_size,
        reserved,
        data_offset,

        header_size,
        width_bytes,
        height_bytes,
        colour_panes,
        depth,
        compression,
        image_size,
        horizontal_res,
        vertical_res,
        palette_count,
        important_colours,

        vec::concat(rows)
    ]);
}*/
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use libc::consts::os::posix88::*;
use libc::funcs::posix88::mman::mmap;
use libc::funcs::posix88::mman::munmap;
use libc::types::common::c95::c_void;
use libc::types::os::arch::c95::size_t;
use std::ptr;
use std::mem;

pub struct Assembler {
    code: Vec<u8>
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { code: Vec::new() }
    }

    pub fn movq(&mut self, dest: Reg64, src: u64) {
        self.code.push(0x48);
        self.code.push(0xB8);
        self.code.write_u64::<LittleEndian>(src).unwrap();
    }

    pub fn nop(&mut self) {
        self.code.push(0x90);
    }

    pub fn ret(&mut self) {
        self.code.push(0xC3);
    }
}

enum Reg64 {
    rax
}

static CODE : [u8;8] = [ 0x48, 0x89, 0xf8, 0x48, 0x83, 0xc0, 0x04, 0xc3 ];

pub struct JitFunction {
    pub size: size_t,
    pub call: extern fn (u64) -> u64
}

impl JitFunction {
    pub fn new(code: &[u8]) -> JitFunction {
        let size = code.len() as u64;

        unsafe {
            let fct = mmap(0 as *mut c_void, size, PROT_READ | PROT_WRITE | PROT_EXEC,
                MAP_PRIVATE | MAP_ANON, -1, 0);

            if fct == MAP_FAILED {
                panic!("mmap failed");
            }

            ptr::copy_nonoverlapping(code.as_ptr() as *const c_void, fct, code.len());

            JitFunction {
                size: size,
                call: mem::transmute(fct)
            }
        }
    }
}

impl Drop for JitFunction {
    fn drop(&mut self) {
        unsafe {
            munmap(mem::transmute(self.call), self.size);
        }
    }
}

#[test]
fn test_create_function() {
    let fct = JitFunction::new(&CODE);

    assert_eq!(5, (fct.call)(1));
}
<commit_msg>better security for generated code<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use libc::consts::os::posix88::*;
use libc::funcs::posix88::mman::mmap;
use libc::funcs::posix88::mman::munmap;
use libc::funcs::posix88::mman::mprotect;
use libc::types::common::c95::c_void;
use libc::types::os::arch::c95::size_t;
use std::ptr;
use std::mem;

pub struct Assembler {
    code: Vec<u8>
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { code: Vec::new() }
    }

    pub fn movq(&mut self, dest: Reg64, src: u64) {
        self.code.push(0x48);
        self.code.push(0xB8);
        self.code.write_u64::<LittleEndian>(src).unwrap();
    }

    pub fn nop(&mut self) {
        self.code.push(0x90);
    }

    pub fn ret(&mut self) {
        self.code.push(0xC3);
    }
}

enum Reg64 {
    rax
}

static CODE : [u8;8] = [ 0x48, 0x89, 0xf8, 0x48, 0x83, 0xc0, 0x04, 0xc3 ];

pub struct JitFunction {
    pub size: size_t,
    pub call: extern fn (u64) -> u64
}

impl JitFunction {
    pub fn new(code: &[u8]) -> JitFunction {
        let size = code.len() as u64;

        unsafe {
            let fct = mmap(0 as *mut c_void, size, PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANON, -1, 0);

            if fct == MAP_FAILED {
                panic!("mmap failed");
            }

            ptr::copy_nonoverlapping(code.as_ptr() as *const c_void, fct, code.len());

            if mprotect(fct, size, PROT_READ | PROT_EXEC) == -1 {
                panic!("mprotect failed");
            }

            JitFunction {
                size: size,
                call: mem::transmute(fct)
            }
        }
    }
}

impl Drop for JitFunction {
    fn drop(&mut self) {
        unsafe {
            munmap(mem::transmute(self.call), self.size);
        }
    }
}

#[test]
fn test_create_function() {
    let fct = JitFunction::new(&CODE);

    assert_eq!(5, (fct.call)(1));
}
<|endoftext|>


<commit_before>use to_javascript::ToJavaScript;

#[derive(Debug, PartialEq)]
pub enum Expression {
    Number(f64),
    Identifier(String),
    Boolean(bool),
    String(String),
    List(Vec<Box<Expression>>),
    FuncLiteral(String, Box<Expression>, Box<Expression>),
    FuncCall(String, Option<Box<Expression>>)
}

/*
impl ToJavaScript for Expression {
    fn eval(&self) -> String {
        match *self {
            Expression::Number(ref val) => format!("{}", val),
            Expression::Identifier(ref val) => format!("{}", val),
            Expression::Boolean(ref val) => format!("{}", val),
            Expression::String(ref val) => val,
            Expression::List(ref vals) => {
                let values = vals
                    .into_iter()
                    .map(|e| e.eval())
                    .collect::<Vec<String>>()
                    .join(",");

                format!("[{}]", values)
            }
        }
    }
}
*/<commit_msg>Make change to AST<commit_after>use to_javascript::ToJavaScript;

#[derive(Debug, PartialEq)]
pub enum Expression {
    Number(f64),
    Identifier(String),
    Boolean(bool),
    String(String),
    List(Vec<Box<Expression>>),

    // String = Function Name, Vec<Box<String>> = Argument List, Box<Expression> = Body
    FuncLiteral(String, Vec<Box<String>>, Box<Expression>),

    // String = Function Name, Vec<Box<Expression>> = Arguments
    FuncCall(String, Vec<Box<Expression>>),
}

/*
impl ToJavaScript for Expression {
    fn eval(&self) -> String {
        match *self {
            Expression::Number(ref val) => format!("{}", val),
            Expression::Identifier(ref val) => format!("{}", val),
            Expression::Boolean(ref val) => format!("{}", val),
            Expression::String(ref val) => val,
            Expression::List(ref vals) => {
                let values = vals
                    .into_iter()
                    .map(|e| e.eval())
                    .collect::<Vec<String>>()
                    .join(",");

                format!("[{}]", values)
            }
        }
    }
}
*/
<|endoftext|>