<commit_before>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> io::Result<StreamReader<R>> {
    let producer  = ReadStream::new(reader);
    let error_str = "parser: couldn't parse the reader";

    Stream::from_stream_producer(producer, error_str)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> io::Result<StreamReader<File>> {
    File::open(filename).and_then(|file| {
      let producer  = ReadStream::new(file);
      let error_str = format!("parser: couldn't parse the given file {}",
                              filename);

      Stream::from_stream_producer(producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> io::Result<StreamBuffer> {
    let producer  = ByteStream::new(buffer);
    let error_str = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(producer, error_str)
  }

  fn from_stream_producer(mut producer: P, error_str: &str)
                          -> io::Result<Self> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    let is_error = many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    });

    if !is_error {
      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      })
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<usize> {
    let stream_info = self.info();

    loop {
      match self.producer.parse(|i| frame_parser(i, &stream_info)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut self.output[start..end];

            subframe::decode(&subframe, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, &mut self.output);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Borrow stream info outside of closure<commit_after>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> io::Result<StreamReader<R>> {
    let producer  = ReadStream::new(reader);
    let error_str = "parser: couldn't parse the reader";

    Stream::from_stream_producer(producer, error_str)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> io::Result<StreamReader<File>> {
    File::open(filename).and_then(|file| {
      let producer  = ReadStream::new(file);
      let error_str = format!("parser: couldn't parse the given file {}",
                              filename);

      Stream::from_stream_producer(producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> io::Result<StreamBuffer> {
    let producer  = ByteStream::new(buffer);
    let error_str = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(producer, error_str)
  }

  fn from_stream_producer(mut producer: P, error_str: &str)
                          -> io::Result<Self> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    let is_error = many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    });

    if !is_error {
      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      })
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<usize> {
    let stream_info = &self.info;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut self.output[start..end];

            subframe::decode(&subframe, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, &mut self.output);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<|endoftext|>


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

use ffi::{self, cairo_status_t};
use {Status, Surface, UserDataKey};

use libc::{c_double, c_uchar, c_uint, c_void};
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::io;
use std::panic::AssertUnwindSafe;
use std::rc::Rc;

macro_rules! for_stream_constructors {
    ($constructor_ffi: ident) => {
        /// Takes full ownership of the output stream,
        /// which is not allowed to borrow any lifetime shorter than `'static`.
        ///
        /// Because the underlying `cairo_surface_t` is reference-counted,
        /// a lifetime parameter in a Rust wrapper type would not be enough to track
        /// how long it can keep writing to the stream.
        pub fn for_stream<W: io::Write + 'static>(width: f64, height: f64, stream: W) -> Result<Self, Status> {
            Ok(Self {
                inner: Surface::_for_stream(ffi::$constructor_ffi, width, height, stream)?,
            })
        }

        /// Allows writing to a borrowed stream. The lifetime of the borrow is not tracked.
        ///
        /// # Safety
        ///
        /// The value that `stream` points to must live at least until the underlying `cairo_surface_t`
        /// (which maybe be longer then the Rust `PdfSurface` wrapper, because of reference-counting),
        /// or until the output stream is removed from the surface with [`Surface::take_output_stream`].
        ///
        /// Since the former is hard to track for sure, the latter is strongly recommended.
        /// The concrete type behind the `Box<dyn Any>` value returned by `take_output_stream`
        /// is private, so you won’t be able to downcast it.
        /// But removing it anyway ensures that later writes do no go through a dangling pointer.
        pub unsafe fn for_raw_stream<W: io::Write + 'static>(
            width: f64,
            height: f64,
            stream: *mut W,
        ) -> Result<Self, Status> {
            Ok(Self {
                inner: Surface::_for_raw_stream(ffi::$constructor_ffi, width, height, stream)?,
            })
        }
    };
}

impl Surface {
    pub(crate) fn _for_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: W,
    ) -> Result<Self, Status> {
        let env_rc = Rc::new(CallbackEnvironment {
            mutable: RefCell::new(MutableCallbackEnvironment {
                stream: Some((Box::new(stream), None)),
                unwind_payload: None,
            }),
            saw_already_borrowed: Cell::new(false),
        });
        let env: *const CallbackEnvironment = &*env_rc;
        unsafe {
            let ptr = constructor(Some(write_callback::<W>), env as *mut c_void, width, height);
            let surface = Surface::from_raw_full(ptr)?;
            surface.set_user_data(&STREAM_CALLBACK_ENVIRONMENT, env_rc);
            Ok(surface)
        }
    }

    pub(crate) unsafe fn _for_raw_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: *mut W,
    ) -> Result<Self, Status> {
        Self::_for_stream(constructor, width, height, RawStream(stream))
    }

    /// Finish the surface, then remove and return the output stream if any.
    ///
    /// This calls [`Surface::finish`], to make sure pending writes are done.
    ///
    /// This is relevant for surfaces created for example with [`PdfSurface::for_stream`].
    ///
    /// Use [`Box::downcast`] to recover the concrete stream type.
    ///
    /// # Panics
    ///
    /// This method panics if:
    ///
    /// * This method was already called for this surface, or
    /// * This surface was not created with an output stream in the first place, or
    /// * A previous write to this surface panicked, or
    /// * A previous write happened while another write was ongoing, or
    /// * A write is ongoing now.
    ///
    /// The latter two cases can only occur with a pathological output stream type
    /// that accesses the same surface again from `Write::write_all`.
    pub fn finish_output_stream(&self) -> Result<Box<dyn Any>, StreamWithError> {
        self.finish();

        let env = self
            .get_user_data_ptr(&STREAM_CALLBACK_ENVIRONMENT)
            .expect("surface without an output stream");

        // Safety: since `STREAM_CALLBACK_ENVIRONMENT` is private and we never
        // call `set_user_data` again or `remove_user_data` with it,
        // the contract of `get_user_data_ptr` says that the user data entry
        // lives as long as the underlying `cairo_surface_t`
        // which is at least as long as `self`.
        let env = unsafe { &*env.as_ptr() };

        if env.saw_already_borrowed.get() {
            panic!(
                "The output stream’s RefCell was already borrowed when cairo attempted a write"
            )
        }

        let mut mutable = env.mutable.borrow_mut();
        if let Some(payload) = mutable.unwind_payload.take() {
            std::panic::resume_unwind(payload)
        }

        let (stream, io_error) = mutable
            .stream
            .take()
            .expect("output stream was already taken");
        if let Some(error) = io_error {
            Err(StreamWithError { stream, error })
        } else {
            Ok(stream)
        }
    }
}

pub struct StreamWithError {
    pub stream: Box<dyn Any>,
    pub error: io::Error,
}

impl std::fmt::Debug for StreamWithError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(f)
    }
}

impl std::fmt::Display for StreamWithError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(f)
    }
}

impl From<StreamWithError> for io::Error {
    fn from(e: StreamWithError) -> Self {
        e.error
    }
}

pub(crate) type Constructor = unsafe extern "C" fn(
    ffi::cairo_write_func_t,
    *mut c_void,
    c_double,
    c_double,
) -> *mut ffi::cairo_surface_t;

static STREAM_CALLBACK_ENVIRONMENT: UserDataKey<CallbackEnvironment> = UserDataKey::new();

struct CallbackEnvironment {
    mutable: RefCell<MutableCallbackEnvironment>,
    saw_already_borrowed: Cell<bool>,
}

struct MutableCallbackEnvironment {
    stream: Option<(Box<dyn Any>, Option<io::Error>)>,
    unwind_payload: Option<Box<dyn Any + Send + 'static>>,
}

// Safety: unwinding into C is undefined behavior (https://github.com/rust-lang/rust/issues/58794)
// so code outside of the `catch_unwind` call must never panic.
extern "C" fn write_callback<W: io::Write + 'static>(
    env: *mut c_void,
    data: *mut c_uchar,
    length: c_uint,
) -> cairo_status_t {
    // This is consistent with the type of `env` in `Surface::_for_stream`.
    let env: *const CallbackEnvironment = env as _;

    // Safety: the user data entry keeps `Rc<CallbackEnvironment>` alive
    // until the surface is destroyed.
    // If this is called by cairo, the surface is still alive.
    let env: &CallbackEnvironment = unsafe { &*env };

    if let Ok(mut mutable) = env.mutable.try_borrow_mut() {
        if let MutableCallbackEnvironment {
            stream:
                Some((
                    stream,
                    // Don’t attempt another write if a previous one errored or panicked:
                    io_error @ None,
                )),
            unwind_payload: unwind_payload @ None,
        } = &mut *mutable
        {
            // Safety: `write_callback<W>` was instanciated in `Surface::_for_stream`
            // with a W parameter consistent with the box that was unsized to `Box<dyn Any>`.
            let stream = unsafe { stream.downcast_mut_unchecked::<W>() };
            // Safety: this is the callback contract from cairo’s API
            let data = unsafe { std::slice::from_raw_parts(data, length as usize) };
            // Because `<W as Write>::write_all` is a generic,
            // we must conservatively assume that it can panic.
            let result = std::panic::catch_unwind(AssertUnwindSafe(|| stream.write_all(data)));
            match result {
                Ok(Ok(())) => return Status::Success.into(),
                Ok(Err(error)) => {
                    *io_error = Some(error);
                }
                Err(payload) => {
                    *unwind_payload = Some(payload);
                }
            }
        }
    } else {
        env.saw_already_borrowed.set(true)
    }
    Status::WriteError.into()
}

struct RawStream<W>(*mut W);

impl<W: io::Write> io::Write for RawStream<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        unsafe { (*self.0).write(buf) }
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        unsafe { (*self.0).write_all(buf) }
    }
    fn flush(&mut self) -> io::Result<()> {
        unsafe { (*self.0).flush() }
    }
}

trait AnyExt {
    /// Any::downcast_mut, but YOLO
    unsafe fn downcast_mut_unchecked<T>(&mut self) -> &mut T {
        let ptr = self as *mut Self as *mut T;
        &mut *ptr
    }
}
impl AnyExt for dyn Any {}
<commit_msg>Use the full Status type name in the for_stream_constructors! macro<commit_after>// Copyright 2019, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi::{self, cairo_status_t};
use {Status, Surface, UserDataKey};

use libc::{c_double, c_uchar, c_uint, c_void};
use std::any::Any;
use std::cell::{Cell, RefCell};
use std::io;
use std::panic::AssertUnwindSafe;
use std::rc::Rc;

macro_rules! for_stream_constructors {
    ($constructor_ffi: ident) => {
        /// Takes full ownership of the output stream,
        /// which is not allowed to borrow any lifetime shorter than `'static`.
        ///
        /// Because the underlying `cairo_surface_t` is reference-counted,
        /// a lifetime parameter in a Rust wrapper type would not be enough to track
        /// how long it can keep writing to the stream.
        pub fn for_stream<W: io::Write + 'static>(width: f64, height: f64, stream: W) -> Result<Self, crate::enums::Status> {
            Ok(Self {
                inner: Surface::_for_stream(ffi::$constructor_ffi, width, height, stream)?,
            })
        }

        /// Allows writing to a borrowed stream. The lifetime of the borrow is not tracked.
        ///
        /// # Safety
        ///
        /// The value that `stream` points to must live at least until the underlying `cairo_surface_t`
        /// (which maybe be longer then the Rust `PdfSurface` wrapper, because of reference-counting),
        /// or until the output stream is removed from the surface with [`Surface::take_output_stream`].
        ///
        /// Since the former is hard to track for sure, the latter is strongly recommended.
        /// The concrete type behind the `Box<dyn Any>` value returned by `take_output_stream`
        /// is private, so you won’t be able to downcast it.
        /// But removing it anyway ensures that later writes do no go through a dangling pointer.
        pub unsafe fn for_raw_stream<W: io::Write + 'static>(
            width: f64,
            height: f64,
            stream: *mut W,
        ) -> Result<Self, crate::enums::Status> {
            Ok(Self {
                inner: Surface::_for_raw_stream(ffi::$constructor_ffi, width, height, stream)?,
            })
        }
    };
}

impl Surface {
    pub(crate) fn _for_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: W,
    ) -> Result<Self, Status> {
        let env_rc = Rc::new(CallbackEnvironment {
            mutable: RefCell::new(MutableCallbackEnvironment {
                stream: Some((Box::new(stream), None)),
                unwind_payload: None,
            }),
            saw_already_borrowed: Cell::new(false),
        });
        let env: *const CallbackEnvironment = &*env_rc;
        unsafe {
            let ptr = constructor(Some(write_callback::<W>), env as *mut c_void, width, height);
            let surface = Surface::from_raw_full(ptr)?;
            surface.set_user_data(&STREAM_CALLBACK_ENVIRONMENT, env_rc);
            Ok(surface)
        }
    }

    pub(crate) unsafe fn _for_raw_stream<W: io::Write + 'static>(
        constructor: Constructor,
        width: f64,
        height: f64,
        stream: *mut W,
    ) -> Result<Self, Status> {
        Self::_for_stream(constructor, width, height, RawStream(stream))
    }

    /// Finish the surface, then remove and return the output stream if any.
    ///
    /// This calls [`Surface::finish`], to make sure pending writes are done.
    ///
    /// This is relevant for surfaces created for example with [`PdfSurface::for_stream`].
    ///
    /// Use [`Box::downcast`] to recover the concrete stream type.
    ///
    /// # Panics
    ///
    /// This method panics if:
    ///
    /// * This method was already called for this surface, or
    /// * This surface was not created with an output stream in the first place, or
    /// * A previous write to this surface panicked, or
    /// * A previous write happened while another write was ongoing, or
    /// * A write is ongoing now.
    ///
    /// The latter two cases can only occur with a pathological output stream type
    /// that accesses the same surface again from `Write::write_all`.
    pub fn finish_output_stream(&self) -> Result<Box<dyn Any>, StreamWithError> {
        self.finish();

        let env = self
            .get_user_data_ptr(&STREAM_CALLBACK_ENVIRONMENT)
            .expect("surface without an output stream");

        // Safety: since `STREAM_CALLBACK_ENVIRONMENT` is private and we never
        // call `set_user_data` again or `remove_user_data` with it,
        // the contract of `get_user_data_ptr` says that the user data entry
        // lives as long as the underlying `cairo_surface_t`
        // which is at least as long as `self`.
        let env = unsafe { &*env.as_ptr() };

        if env.saw_already_borrowed.get() {
            panic!(
                "The output stream’s RefCell was already borrowed when cairo attempted a write"
            )
        }

        let mut mutable = env.mutable.borrow_mut();
        if let Some(payload) = mutable.unwind_payload.take() {
            std::panic::resume_unwind(payload)
        }

        let (stream, io_error) = mutable
            .stream
            .take()
            .expect("output stream was already taken");
        if let Some(error) = io_error {
            Err(StreamWithError { stream, error })
        } else {
            Ok(stream)
        }
    }
}

pub struct StreamWithError {
    pub stream: Box<dyn Any>,
    pub error: io::Error,
}

impl std::fmt::Debug for StreamWithError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(f)
    }
}

impl std::fmt::Display for StreamWithError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(f)
    }
}

impl From<StreamWithError> for io::Error {
    fn from(e: StreamWithError) -> Self {
        e.error
    }
}

pub(crate) type Constructor = unsafe extern "C" fn(
    ffi::cairo_write_func_t,
    *mut c_void,
    c_double,
    c_double,
) -> *mut ffi::cairo_surface_t;

static STREAM_CALLBACK_ENVIRONMENT: UserDataKey<CallbackEnvironment> = UserDataKey::new();

struct CallbackEnvironment {
    mutable: RefCell<MutableCallbackEnvironment>,
    saw_already_borrowed: Cell<bool>,
}

struct MutableCallbackEnvironment {
    stream: Option<(Box<dyn Any>, Option<io::Error>)>,
    unwind_payload: Option<Box<dyn Any + Send + 'static>>,
}

// Safety: unwinding into C is undefined behavior (https://github.com/rust-lang/rust/issues/58794)
// so code outside of the `catch_unwind` call must never panic.
extern "C" fn write_callback<W: io::Write + 'static>(
    env: *mut c_void,
    data: *mut c_uchar,
    length: c_uint,
) -> cairo_status_t {
    // This is consistent with the type of `env` in `Surface::_for_stream`.
    let env: *const CallbackEnvironment = env as _;

    // Safety: the user data entry keeps `Rc<CallbackEnvironment>` alive
    // until the surface is destroyed.
    // If this is called by cairo, the surface is still alive.
    let env: &CallbackEnvironment = unsafe { &*env };

    if let Ok(mut mutable) = env.mutable.try_borrow_mut() {
        if let MutableCallbackEnvironment {
            stream:
                Some((
                    stream,
                    // Don’t attempt another write if a previous one errored or panicked:
                    io_error @ None,
                )),
            unwind_payload: unwind_payload @ None,
        } = &mut *mutable
        {
            // Safety: `write_callback<W>` was instanciated in `Surface::_for_stream`
            // with a W parameter consistent with the box that was unsized to `Box<dyn Any>`.
            let stream = unsafe { stream.downcast_mut_unchecked::<W>() };
            // Safety: this is the callback contract from cairo’s API
            let data = unsafe { std::slice::from_raw_parts(data, length as usize) };
            // Because `<W as Write>::write_all` is a generic,
            // we must conservatively assume that it can panic.
            let result = std::panic::catch_unwind(AssertUnwindSafe(|| stream.write_all(data)));
            match result {
                Ok(Ok(())) => return Status::Success.into(),
                Ok(Err(error)) => {
                    *io_error = Some(error);
                }
                Err(payload) => {
                    *unwind_payload = Some(payload);
                }
            }
        }
    } else {
        env.saw_already_borrowed.set(true)
    }
    Status::WriteError.into()
}

struct RawStream<W>(*mut W);

impl<W: io::Write> io::Write for RawStream<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        unsafe { (*self.0).write(buf) }
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        unsafe { (*self.0).write_all(buf) }
    }
    fn flush(&mut self) -> io::Result<()> {
        unsafe { (*self.0).flush() }
    }
}

trait AnyExt {
    /// Any::downcast_mut, but YOLO
    unsafe fn downcast_mut_unchecked<T>(&mut self) -> &mut T {
        let ptr = self as *mut Self as *mut T;
        &mut *ptr
    }
}
impl AnyExt for dyn Any {}
<|endoftext|>


<commit_before>//! Target information

use super::prelude::*;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeAMDGPUTargetInfo();
    pub fn LLVMInitializeAMDGPUTarget();
    pub fn LLVMInitializeAMDGPUTargetMC();
    pub fn LLVMInitializeAMDGPUAsmPrinter();
    pub fn LLVMInitializeAMDGPUAsmParser();
    // Disassembler?

    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeSystemZDisassembler();

    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeHexagonAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeHexagonDisassembler();

    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeCppBackendTargetInfo();
    pub fn LLVMInitializeCppBackendTarget();
    pub fn LLVMInitializeCppBackendTargetMC();
    // AsmPrinter?
    // AsmParser?

    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeMSP430AsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeXCoreAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeXCoreDisassembler();

    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeMipsDisassembler();

    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeAArch64Disassembler();

    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializeARMDisassembler();

    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializePowerPCDisassembler();

    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeSparcDisassembler();

    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeX86Disassembler();

    pub fn LLVMInitializeBPFTargetInfo();
    pub fn LLVMInitializeBPFTarget();
    pub fn LLVMInitializeBPFTargetMC();
    pub fn LLVMInitializeBPFAsmPrinter();
    // No AsmParser
    pub fn LLVMInitializeBPFDisassembler();

    pub fn LLVMInitializeLanaiTargetInfo();
    pub fn LLVMInitializeLanaiTarget();
    pub fn LLVMInitializeLanaiTargetMC();
    pub fn LLVMInitializeLanaiAsmPrinter();
    pub fn LLVMInitializeLanaiAsmParser();
    pub fn LLVMInitializeLanaiDisassembler();

    pub fn LLVMInitializeRISCVTargetInfo();
    pub fn LLVMInitializeRISCVTarget();
    pub fn LLVMInitializeRISCVTargetMC();
    // No AsmPrinter
    // No AsmParser
    // No Disassembler
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<commit_msg>Remove Cpp backend.<commit_after>//! Target information

use super::prelude::*;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeAMDGPUTargetInfo();
    pub fn LLVMInitializeAMDGPUTarget();
    pub fn LLVMInitializeAMDGPUTargetMC();
    pub fn LLVMInitializeAMDGPUAsmPrinter();
    pub fn LLVMInitializeAMDGPUAsmParser();
    // Disassembler?

    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeSystemZDisassembler();

    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeHexagonAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeHexagonDisassembler();

    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeMSP430AsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeXCoreAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeXCoreDisassembler();

    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeMipsDisassembler();

    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeAArch64Disassembler();

    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializeARMDisassembler();

    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializePowerPCDisassembler();

    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeSparcDisassembler();

    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeX86Disassembler();

    pub fn LLVMInitializeBPFTargetInfo();
    pub fn LLVMInitializeBPFTarget();
    pub fn LLVMInitializeBPFTargetMC();
    pub fn LLVMInitializeBPFAsmPrinter();
    // No AsmParser
    pub fn LLVMInitializeBPFDisassembler();

    pub fn LLVMInitializeLanaiTargetInfo();
    pub fn LLVMInitializeLanaiTarget();
    pub fn LLVMInitializeLanaiTargetMC();
    pub fn LLVMInitializeLanaiAsmPrinter();
    pub fn LLVMInitializeLanaiAsmParser();
    pub fn LLVMInitializeLanaiDisassembler();

    pub fn LLVMInitializeRISCVTargetInfo();
    pub fn LLVMInitializeRISCVTarget();
    pub fn LLVMInitializeRISCVTargetMC();
    // No AsmPrinter
    // No AsmParser
    // No Disassembler
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<|endoftext|>


<commit_before>/// Scoped thread.
///
/// # Examples
///
/// A basic scoped thread:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.spawn(|| {
///         println!("Hello from a scoped thread!");
///     });
/// });
/// ```
///
/// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using
/// [`std::thread::spawn`][spawn]:
///
/// ```ignore
/// let array = [1, 2, 3];
/// let mut guards = vec![];
///
/// for i in &array {
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", i);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// The basic pattern is:
///
/// 1. Iterate over some collection.
/// 2. Spin up a thread to operate on each part of the collection.
/// 3. Join all the threads.
///
/// However, this code actually gives an error:
///
/// ```text
/// error: `array` does not live long enough
/// for i in &array {
///           ^~~~~
/// in expansion of for loop expansion
/// note: expansion site
/// note: reference must be valid for the static lifetime...
/// note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
///     let array = [1, 2, 3];
///     let mut guards = vec![];
///
///     for i in &array {
///         let guard = std::thread::spawn(move || {
///             println!("element: {}", i);
/// ...
/// error: aborting due to previous error
/// ```
///
/// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a
/// `'static` lifetime. One way of giving it a proper lifetime is to use an [`Arc`][arc]:
///
/// [arc]: http://doc.rust-lang.org/stable/std/sync/struct.Arc.html
/// [spawn]: https://doc.rust-lang.org/stable/std/thread/fn.spawn.html
///
/// ```
/// use std::sync::Arc;
///
/// let array = Arc::new([1, 2, 3]);
/// let mut guards = vec![];
///
/// for i in 0..array.len() {
///     let a = array.clone();
///
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", a[i]);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// But this introduces unnecessary allocation, as `Arc<T>` puts its data on the heap, and we
/// also end up dealing with reference counts. We know that we're joining the threads before
/// our function returns, so just taking a reference _should_ be safe. Rust can't know that,
/// though.
///
/// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather
/// than from `std::thread`:
///
/// ```
/// let array = [1, 2, 3];
///
/// crossbeam_utils::thread::scope(|scope| {
///     for i in &array {
///         scope.spawn(move || {
///             println!("element: {}", i);
///         });
///     }
/// });
/// ```
///
/// Much more straightforward.
// FIXME(jeehoonkang): maybe we should create a new crate for scoped threads.

use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ops::DerefMut;
use std::rc::Rc;
use std::thread;
use std::io;

#[doc(hidden)]
trait FnBox<T> {
    fn call_box(self: Box<Self>) -> T;
}

impl<T, F: FnOnce() -> T> FnBox<T> for F {
    fn call_box(self: Box<Self>) -> T {
        (*self)()
    }
}

/// Like `std::thread::spawn`, but without the closure bounds.
pub unsafe fn spawn_unchecked<'a, F>(f: F) -> thread::JoinHandle<()>
where
    F: FnOnce() + Send + 'a,
{
    let builder = thread::Builder::new();
    builder_spawn_unchecked(builder, f).unwrap()
}

/// Like `std::thread::Builder::spawn`, but without the closure bounds.
pub unsafe fn builder_spawn_unchecked<'a, F>(
    builder: thread::Builder,
    f: F,
) -> io::Result<thread::JoinHandle<()>>
where
    F: FnOnce() + Send + 'a,
{
    let closure: Box<FnBox<()> + 'a> = Box::new(f);
    let closure: Box<FnBox<()> + Send> = mem::transmute(closure);
    builder.spawn(move || closure.call_box())
}

pub struct Scope<'a> {
    /// The list of the deferred functions and thread join jobs.
    dtors: RefCell<Option<DtorChain<'a, ()>>>,
    // !Send + !Sync
    _marker: PhantomData<*const ()>,
}

struct DtorChain<'a, T> {
    dtor: Box<FnBox<T> + 'a>,
    next: Option<Box<DtorChain<'a, T>>>,
}

impl<'a, T> DtorChain<'a, T> {
    pub fn pop(chain: &mut Option<DtorChain<'a, T>>) -> Option<Box<FnBox<T> + 'a>> {
        chain.take().map(|mut node| {
            *chain = node.next.take().map(|b| *b);
            node.dtor
        })
    }
}

struct JoinState<T> {
    join_handle: thread::JoinHandle<()>,
    result: usize,
    _marker: PhantomData<T>,
}

impl<T: Send> JoinState<T> {
    fn new(join_handle: thread::JoinHandle<()>, result: usize) -> JoinState<T> {
        JoinState {
            join_handle: join_handle,
            result: result,
            _marker: PhantomData,
        }
    }

    fn join(self) -> thread::Result<T> {
        let result = self.result;
        self.join_handle.join().map(|_| {
            unsafe { ManuallyDrop::into_inner(*Box::from_raw(result as *mut ManuallyDrop<T>))}
        })
    }
}

/// A handle to a scoped thread
pub struct ScopedJoinHandle<'a, T: 'a> {
    // !Send + !Sync
    inner: Rc<RefCell<Option<JoinState<T>>>>,
    thread: thread::Thread,
    _marker: PhantomData<&'a T>,
}

/// Create a new `scope`, for deferred destructors.
///
/// Scopes, in particular, support [*scoped thread spawning*](struct.Scope.html#method.spawn).
///
/// # Examples
///
/// Creating and using a scope:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.defer(|| println!("Exiting scope"));
///     scope.spawn(|| println!("Running child thread in scope"))
/// });
/// // Prints messages in the reverse order written
/// ```
///
/// # Panics
///
/// `thread::scope()` panics if a spawned thread panics but it is not joined inside the scope.
pub fn scope<'a, F, R>(f: F) -> R
where
    F: FnOnce(&Scope<'a>) -> R,
{
    let mut scope = Scope {
        dtors: RefCell::new(None),
        _marker: PhantomData,
    };
    let ret = f(&scope);
    scope.drop_all();
    ret
}

impl<'a> fmt::Debug for Scope<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope {{ ... }}")
    }
}

impl<'a, T> fmt::Debug for ScopedJoinHandle<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ScopedJoinHandle {{ ... }}")
    }
}

impl<'a> Scope<'a> {
    // This method is carefully written in a transactional style, so
    // that it can be called directly and, if any dtor panics, can be
    // resumed in the unwinding this causes. By initially running the
    // method outside of any destructor, we avoid any leakage problems
    // due to @rust-lang/rust#14875.
    fn drop_all(&mut self) {
        while let Some(dtor) = DtorChain::pop(&mut self.dtors.borrow_mut()) {
            dtor.call_box();
        }
    }

    /// Schedule code to be executed when exiting the scope.
    ///
    /// This is akin to having a destructor on the stack, except that it is
    /// *guaranteed* to be run. It is guaranteed that the function is called
    /// after all the spawned threads are joined.
    pub fn defer<F>(&self, f: F)
    where
        F: FnOnce() + 'a,
    {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new),
        });
    }

    /// Create a scoped thread.
    ///
    /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The
    /// difference is that this thread is scoped, meaning that it's guaranteed to terminate
    /// before the current stack frame goes away, allowing you to reference the parent stack frame
    /// directly. This is ensured by having the parent thread join on the child thread before the
    /// scope exits.
    ///
    /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html
    pub fn spawn<'s, F, T>(&'s self, f: F) -> ScopedJoinHandle<'a, T>
    where
        'a: 's,
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        self.builder().spawn(f).unwrap()
    }

    /// Generates the base configuration for spawning a scoped thread, from which configuration
    /// methods can be chained.
    pub fn builder<'s>(&'s self) -> ScopedThreadBuilder<'s, 'a> {
        ScopedThreadBuilder {
            scope: self,
            builder: thread::Builder::new(),
        }
    }
}

/// Scoped thread configuration. Provides detailed control over the properties and behavior of new
/// scoped threads.
pub struct ScopedThreadBuilder<'s, 'a: 's> {
    scope: &'s Scope<'a>,
    builder: thread::Builder,
}

impl<'s, 'a: 's> ScopedThreadBuilder<'s, 'a> {
    /// Names the thread-to-be. Currently the name is used for identification only in panic
    /// messages.
    pub fn name(mut self, name: String) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.name(name);
        self
    }

    /// Sets the size of the stack for the new thread.
    pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.stack_size(size);
        self
    }

    /// Spawns a new thread, and returns a join handle for it.
    pub fn spawn<F, T>(self, f: F) -> io::Result<ScopedJoinHandle<'a, T>>
    where
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        // The `Box` constructed below is written only by the spawned thread,
        // and read by the current thread only after the spawned thread is
        // joined (`JoinState::join()`). Thus there are no data races.
        let result = Box::into_raw(Box::<ManuallyDrop<T>>::new(unsafe { mem::uninitialized() })) as usize;

        let join_handle = try!(unsafe {
            builder_spawn_unchecked(self.builder, move || {
                let mut result = Box::from_raw(result as *mut ManuallyDrop<T>);
                *result = ManuallyDrop::new(f());
                mem::forget(result);
            })
        });
        let thread = join_handle.thread().clone();

        let join_state = JoinState::<T>::new(join_handle, result);
        let deferred_handle = Rc::new(RefCell::new(Some(join_state)));
        let my_handle = deferred_handle.clone();

        self.scope.defer(move || {
            let state = mem::replace(deferred_handle.borrow_mut().deref_mut(), None);
            if let Some(state) = state {
                state.join().unwrap();
            }
        });

        Ok(ScopedJoinHandle {
            inner: my_handle,
            thread: thread,
            _marker: PhantomData,
        })
    }
}

impl<'a, T: Send + 'a> ScopedJoinHandle<'a, T> {
    /// Join the scoped thread, returning the result it produced.
    pub fn join(self) -> thread::Result<T> {
        let state = mem::replace(self.inner.borrow_mut().deref_mut(), None);
        state.unwrap().join()
    }

    /// Get the underlying thread handle.
    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'a> Drop for Scope<'a> {
    fn drop(&mut self) {
        self.drop_all()
    }
}
<commit_msg>Fix bugs in thread::scope()<commit_after>/// Scoped thread.
///
/// # Examples
///
/// A basic scoped thread:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.spawn(|| {
///         println!("Hello from a scoped thread!");
///     });
/// });
/// ```
///
/// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using
/// [`std::thread::spawn`][spawn]:
///
/// ```ignore
/// let array = [1, 2, 3];
/// let mut guards = vec![];
///
/// for i in &array {
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", i);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// The basic pattern is:
///
/// 1. Iterate over some collection.
/// 2. Spin up a thread to operate on each part of the collection.
/// 3. Join all the threads.
///
/// However, this code actually gives an error:
///
/// ```text
/// error: `array` does not live long enough
/// for i in &array {
///           ^~~~~
/// in expansion of for loop expansion
/// note: expansion site
/// note: reference must be valid for the static lifetime...
/// note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
///     let array = [1, 2, 3];
///     let mut guards = vec![];
///
///     for i in &array {
///         let guard = std::thread::spawn(move || {
///             println!("element: {}", i);
/// ...
/// error: aborting due to previous error
/// ```
///
/// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a
/// `'static` lifetime. One way of giving it a proper lifetime is to use an [`Arc`][arc]:
///
/// [arc]: http://doc.rust-lang.org/stable/std/sync/struct.Arc.html
/// [spawn]: https://doc.rust-lang.org/stable/std/thread/fn.spawn.html
///
/// ```
/// use std::sync::Arc;
///
/// let array = Arc::new([1, 2, 3]);
/// let mut guards = vec![];
///
/// for i in 0..array.len() {
///     let a = array.clone();
///
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", a[i]);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// But this introduces unnecessary allocation, as `Arc<T>` puts its data on the heap, and we
/// also end up dealing with reference counts. We know that we're joining the threads before
/// our function returns, so just taking a reference _should_ be safe. Rust can't know that,
/// though.
///
/// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather
/// than from `std::thread`:
///
/// ```
/// let array = [1, 2, 3];
///
/// crossbeam_utils::thread::scope(|scope| {
///     for i in &array {
///         scope.spawn(move || {
///             println!("element: {}", i);
///         });
///     }
/// });
/// ```
///
/// Much more straightforward.

use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ops::DerefMut;
use std::panic::{self, AssertUnwindSafe};
use std::rc::Rc;
use std::thread;
use std::io;

#[doc(hidden)]
trait FnBox<T> {
    fn call_box(self: Box<Self>) -> T;
}

impl<T, F: FnOnce() -> T> FnBox<T> for F {
    fn call_box(self: Box<Self>) -> T {
        (*self)()
    }
}

/// Like `std::thread::spawn`, but without the closure bounds.
pub unsafe fn spawn_unchecked<'a, F>(f: F) -> thread::JoinHandle<()>
where
    F: FnOnce() + Send + 'a,
{
    let builder = thread::Builder::new();
    builder_spawn_unchecked(builder, f).unwrap()
}

/// Like `std::thread::Builder::spawn`, but without the closure bounds.
pub unsafe fn builder_spawn_unchecked<'a, F>(
    builder: thread::Builder,
    f: F,
) -> io::Result<thread::JoinHandle<()>>
where
    F: FnOnce() + Send + 'a,
{
    let closure: Box<FnBox<()> + 'a> = Box::new(f);
    let closure: Box<FnBox<()> + Send> = mem::transmute(closure);
    builder.spawn(move || closure.call_box())
}

pub struct Scope<'a> {
    /// The list of the deferred functions and thread join jobs.
    dtors: RefCell<Option<DtorChain<'a, thread::Result<()>>>>,
    // !Send + !Sync
    _marker: PhantomData<*const ()>,
}

struct DtorChain<'a, T> {
    dtor: Box<FnBox<T> + 'a>,
    next: Option<Box<DtorChain<'a, T>>>,
}

impl<'a, T> DtorChain<'a, T> {
    pub fn pop(chain: &mut Option<DtorChain<'a, T>>) -> Option<Box<FnBox<T> + 'a>> {
        chain.take().map(|mut node| {
            *chain = node.next.take().map(|b| *b);
            node.dtor
        })
    }
}

struct JoinState<T> {
    join_handle: thread::JoinHandle<()>,
    result: usize,
    _marker: PhantomData<T>,
}

impl<T: Send> JoinState<T> {
    fn new(join_handle: thread::JoinHandle<()>, result: usize) -> JoinState<T> {
        JoinState {
            join_handle: join_handle,
            result: result,
            _marker: PhantomData,
        }
    }

    fn join(self) -> thread::Result<T> {
        let result = self.result;
        self.join_handle.join().map(|_| {
            unsafe { ManuallyDrop::into_inner(*Box::from_raw(result as *mut ManuallyDrop<T>))}
        })
    }
}

/// A handle to a scoped thread
pub struct ScopedJoinHandle<'a, T: 'a> {
    // !Send + !Sync
    inner: Rc<RefCell<Option<JoinState<T>>>>,
    thread: thread::Thread,
    _marker: PhantomData<&'a T>,
}

/// Create a new `Scope` for [*scoped thread spawning*](struct.Scope.html#method.spawn).
///
/// In addition, you can [register ad-hoc functions](struct.Scope.html#method.defer) that are
/// deferred to be run. No matter what happens, before the `Scope` is dropped, it is guaranteed that
/// all the unjoined spawned scoped threads are joined and the deferred functions are run.
///
/// `thread::scope()` returns `Ok(())` if all the unjoined spawned threads and the deferred
/// functions did not panic. It returns `Err(e)` if one of them panics with `e`. If many of them
/// panics, it is still guaranteed that all the threads are joined and all the functions are run,
/// and `thread::scope()` returns `Err(e)` with `e` from a panicking thread or function.
///
/// # Examples
///
/// Creating and using a scope:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.defer(|| println!("Exiting scope"));
///     scope.spawn(|| println!("Running child thread in scope"))
/// }).unwrap();
/// // Prints messages
/// ```
pub fn scope<'a, F, R>(f: F) -> thread::Result<R>
where
    F: FnOnce(&Scope<'a>) -> R,
{
    let mut scope = Scope {
        dtors: RefCell::new(None),
        _marker: PhantomData,
    };
    let ret = f(&scope);
    scope.drop_all()?;
    Ok(ret)
}

impl<'a> fmt::Debug for Scope<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope {{ ... }}")
    }
}

impl<'a, T> fmt::Debug for ScopedJoinHandle<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ScopedJoinHandle {{ ... }}")
    }
}

impl<'a> Scope<'a> {
    // This method is carefully written in a transactional style, so that it can be called directly
    // and, if any dtor panics, can be resumed in the unwinding this causes. By initially running
    // the method outside of any destructor, we avoid any leakage problems due to
    // @rust-lang/rust#14875.
    fn drop_all(&mut self) -> thread::Result<()> {
        let mut ret = Ok(());
        while let Some(dtor) = DtorChain::pop(&mut self.dtors.borrow_mut()) {
            ret = ret.and(dtor.call_box());
        }
        ret
    }

    fn defer_inner<F>(&self, f: F)
    where
        F: (FnOnce() -> thread::Result<()>) + 'a,
    {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new),
        });
    }

    /// Schedule code to be executed when exiting the scope.
    ///
    /// This is akin to having a destructor on the stack, except that it is *guaranteed* to be
    /// run. It is guaranteed that the function is called after all the spawned threads are joined.
    pub fn defer<F>(&self, f: F)
    where
        F: FnOnce() + 'a,
    {
        self.defer_inner(move || panic::catch_unwind(AssertUnwindSafe(f)));
    }

    /// Create a scoped thread.
    ///
    /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The
    /// difference is that this thread is scoped, meaning that it's guaranteed to terminate before
    /// the current stack frame goes away, allowing you to reference the parent stack frame
    /// directly. This is ensured by having the parent thread join on the child thread before the
    /// scope exits.
    ///
    /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html
    pub fn spawn<'s, F, T>(&'s self, f: F) -> ScopedJoinHandle<'a, T>
    where
        'a: 's,
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        self.builder().spawn(f).unwrap()
    }

    /// Generates the base configuration for spawning a scoped thread, from which configuration
    /// methods can be chained.
    pub fn builder<'s>(&'s self) -> ScopedThreadBuilder<'s, 'a> {
        ScopedThreadBuilder {
            scope: self,
            builder: thread::Builder::new(),
        }
    }
}

/// Scoped thread configuration. Provides detailed control over the properties and behavior of new
/// scoped threads.
pub struct ScopedThreadBuilder<'s, 'a: 's> {
    scope: &'s Scope<'a>,
    builder: thread::Builder,
}

impl<'s, 'a: 's> ScopedThreadBuilder<'s, 'a> {
    /// Names the thread-to-be. Currently the name is used for identification only in panic
    /// messages.
    pub fn name(mut self, name: String) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.name(name);
        self
    }

    /// Sets the size of the stack for the new thread.
    pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'s, 'a> {
        self.builder = self.builder.stack_size(size);
        self
    }

    /// Spawns a new thread, and returns a join handle for it.
    pub fn spawn<F, T>(self, f: F) -> io::Result<ScopedJoinHandle<'a, T>>
    where
        F: FnOnce() -> T + Send + 'a,
        T: Send + 'a,
    {
        // The `Box` constructed below is written only by the spawned thread, and read by the
        // current thread only after the spawned thread is joined (`JoinState::join()`). Thus there
        // are no data races.
        let result = Box::into_raw(Box::<ManuallyDrop<T>>::new(unsafe { mem::uninitialized() })) as usize;

        let join_handle = try!(unsafe {
            builder_spawn_unchecked(self.builder, move || {
                let mut result = Box::from_raw(result as *mut ManuallyDrop<T>);
                *result = ManuallyDrop::new(f());
                mem::forget(result);
            })
        });
        let thread = join_handle.thread().clone();

        let join_state = JoinState::<T>::new(join_handle, result);
        let deferred_handle = Rc::new(RefCell::new(Some(join_state)));
        let my_handle = deferred_handle.clone();

        self.scope.defer_inner(move || {
            let state = mem::replace(deferred_handle.borrow_mut().deref_mut(), None);
            if let Some(state) = state {
                state.join().map(|_| ())
            } else {
                Ok(())
            }
        });

        Ok(ScopedJoinHandle {
            inner: my_handle,
            thread: thread,
            _marker: PhantomData,
        })
    }
}

impl<'a, T: Send + 'a> ScopedJoinHandle<'a, T> {
    /// Waits for the associated thread to finish.
    ///
    /// If the child thread panics, [`Err`] is returned with the parameter given to [`panic`].
    ///
    /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
    /// [`panic`]: https://doc.rust-lang.org/std/macro.panic.html
    ///
    /// # Panics
    ///
    /// This function may panic on some platforms if a thread attempts to join itself or otherwise
    /// may create a deadlock with joining threads.
    pub fn join(self) -> thread::Result<T> {
        let state = mem::replace(self.inner.borrow_mut().deref_mut(), None);
        state.unwrap().join()
    }

    /// Gets the underlying [`std::thread::Thread`] handle.
    ///
    /// [`std::thread::Thread`]: https://doc.rust-lang.org/std/thread/struct.Thread.html
    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'a> Drop for Scope<'a> {
    fn drop(&mut self) {
        // Actually, there should be no deferred functions left to be run.
        self.drop_all().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::{PathBuf, Path};
use config::Config;

#[derive(Debug, Clone, Default, Hash, PartialEq, Eq, PartialOrd)]
pub struct Trace {
    pub line: u64,
    pub address: Option<u64>,
    pub hits: u64,
}

pub struct TraceMap<'a> {
    traces: HashMap<PathBuf, Vec<Trace>>,
    config: &'a Config
}

impl<'a> TraceMap<'a> {

    pub fn new(config: &'a Config) -> TraceMap<'a> {
        TraceMap {
            config: config,
            traces: HashMap::new(),
        }
    }

    pub fn get_child_traces(&self, root: &Path) -> Vec<&Trace> {
        self.traces.iter()
                   .filter(|&(ref k, _)| k.starts_with(root))
                   .flat_map(|(_, ref v)| v.iter())
                   .collect()
    }
}
<commit_msg>Switched HashMap to BTreeMap<commit_after>use std::collections::BTreeMap;
use std::path::{PathBuf, Path};
use config::Config;

#[derive(Debug, Clone, Default, Hash, PartialEq, Eq, PartialOrd)]
pub struct Trace {
    pub line: u64,
    pub address: Option<u64>,
    pub hits: u64,
}

pub struct TraceMap<'a> {
    traces: BTreeMap<PathBuf, Vec<Trace>>,
    config: &'a Config
}

impl<'a> TraceMap<'a> {

    pub fn new(config: &'a Config) -> TraceMap<'a> {
        TraceMap {
            config: config,
            traces: BTreeMap::new(),
        }
    }

    pub fn get_child_traces(&self, root: &Path) -> Vec<&Trace> {
        self.traces.iter()
                   .filter(|&(ref k, _)| k.starts_with(root))
                   .flat_map(|(_, ref v)| v.iter())
                   .collect()
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate rocket_contrib;
extern crate rustyweb;
#[macro_use]
extern crate lazy_static;
extern crate base64;
extern crate serde;
extern crate untrusted;
extern crate ring;
extern crate chrono;

use std::sync::RwLock;

use rocket::State;
use rocket_contrib::{Json};

use rustyweb::*;

#[get("/")]
fn hello() -> String {
    format!("Hello world")
}

#[get("/id/<id>")]
fn get_id(id: String, serverdata: State<RwLock<ServerData>>) -> Option<String> {
    if let Some(key) = serverdata.read().unwrap().get_id_key(&id) {
        Some(base64::encode(key))
    } else {
        None
    }
}

#[get("/name/<name>", format = "application/json")]
fn get_name(name: String, serverdata: State<RwLock<ServerData>>) -> Option<Json<UpdateMessage>> {
    if let Some(n) = serverdata.read().unwrap().get_name(&name) {
        Some(Json((*n).clone()))
    } else {
        None
    }
}

// What I CAN'T figure out is how to make this return a 403 if
// the user is not authorized.  Returning a Result just turns into
// a 500 error on Err, it seems, and I'm sick of searching for this
// one thing.
#[post("/name/<name>", format = "application/json", data = "<msg>")]
fn post_name(name: String, msg: Json<UpdateMessage>, serverdata: State<RwLock<ServerData>>) -> Result<String, ValidationError> {
    serverdata.write().unwrap().apply_update_if_valid(&name, &msg.0).map(|_| "ok".to_string())
}

fn run(server_data: ServerData, port: u16) {
    let config = rocket::config::Config::build(rocket::config::Environment::Staging)
        .port(port)
        .finalize().expect("Could not create config");

    rocket::custom(config, false)
        .mount("/", routes![hello, get_name, get_id, post_name])
        .manage(RwLock::new(server_data))
        .launch();

}

fn main() {
    let server_data = ServerData::default();
    run(server_data, 8888)
}

#[cfg(test)]
mod tests {
    extern crate reqwest;
    use lazy_static;
    use std::thread;
    use std::io::Read;
    use serde::Serialize;
    use ring::{rand, signature};
    use untrusted;
    use base64;
    use chrono::prelude::*;
    use super::UpdateMessage;

    const UNITTEST_USER: &str = "unittest_user";
    const UNITTEST_NAME: &str = "unittest_name";

    fn start_test_server() {
        use super::ServerData;
        let mut s = ServerData::default();
        let pubkey_bytes = KEYPAIR.public_key_bytes();
        s.add_id(UNITTEST_USER, pubkey_bytes);
        s.update_name(UNITTEST_NAME, &UNITTEST_NAME_VALUE);
        super::run(s, 8888);
    }

    fn generate_keypair() -> signature::Ed25519KeyPair {
        let rng = rand::SystemRandom::new();
        let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
        let keypair = signature::Ed25519KeyPair::from_pkcs8(
            untrusted::Input::from(&pkcs8_bytes)
        ).unwrap();
        keypair
    }

    lazy_static! {
        static ref SERVER_THREAD: thread::JoinHandle<()> = thread::spawn(start_test_server);
        static ref KEYPAIR: signature::Ed25519KeyPair = generate_keypair();
        static ref UNITTEST_NAME_VALUE: UpdateMessage = UpdateMessage::signed_message(&KEYPAIR, UNITTEST_USER, "unittest_value");
    }

    fn spawn_server_and_get(path: &str) -> reqwest::Response {
        lazy_static::initialize(&SERVER_THREAD);
        let new_path = String::from("http://localhost:8888") + path;
        reqwest::get(&new_path).unwrap()
    }

    fn spawn_server_and_post<T: Serialize>(path: &str, json: &T) -> reqwest::Response {
        lazy_static::initialize(&SERVER_THREAD);
        let client = reqwest::Client::new().unwrap();
        let new_path = String::from("http://localhost:8888") + path;
        client.post(&new_path).unwrap()
            .json(json).unwrap()
            .send().unwrap()
    }

    #[test]
    fn test_basic() {
        let mut resp = spawn_server_and_get("/");
        assert!(resp.status().is_success());
        let mut content = String::new();
        resp.read_to_string(&mut content).unwrap();
        assert_eq!(content, "Hello world");
    }

    #[test]
    fn test_id() {
        let mut resp = spawn_server_and_get((String::from("/id/") + UNITTEST_USER).as_str());
        assert!(resp.status().is_success());
        let mut content = String::new();
        resp.read_to_string(&mut content).unwrap();
        let pubkey_bytes = KEYPAIR.public_key_bytes();
        let pubkey_string = base64::encode(pubkey_bytes);
        assert_eq!(content, pubkey_string);
    }

    #[test]
    fn test_get_name() {
        // Test unset name default
        let resp = spawn_server_and_get("/name/test_no_name");
        assert_eq!(resp.status(), reqwest::StatusCode::NotFound);

        // Test set name
        let mut resp = spawn_server_and_get((String::from("/name/") + UNITTEST_NAME).as_str());
        assert!(resp.status().is_success());
        let resp_msg: UpdateMessage = resp.json().unwrap();
        assert_eq!(resp_msg, *UNITTEST_NAME_VALUE);
    }

    #[test]
    fn test_post_name() {
        const NEWNAME: &str = "/name/test_post_name";
        // See that name DNE
        let resp = spawn_server_and_get(NEWNAME);
        assert!(!resp.status().is_success());

        let changed_name = "foo!";
        let data = super::UpdateMessage::signed_message(&KEYPAIR, UNITTEST_USER, changed_name);

        // Change name
        let mut resp = spawn_server_and_post(NEWNAME, &data);
        assert!(resp.status().is_success());
        let mut content = String::new();
        resp.read_to_string(&mut content).unwrap();
        assert_eq!(content, "ok");

        // Test name now that it's been changed
        let mut resp = spawn_server_and_get(NEWNAME);
        assert!(resp.status().is_success());
        let resp_msg: UpdateMessage = resp.json().unwrap();
        assert_eq!(resp_msg, data);

        // Try changing it again with unsigned request
        let baddata = super::UpdateMessage {
            user: UNITTEST_USER.into(),
            utc: Utc::now(),
            signature: "".into(),
            new_contents: "aieeee!".into(),
        };
        let resp = spawn_server_and_post(NEWNAME, &baddata);
        assert!(!resp.status().is_success());

        // Ensure it hasn't changed.
        let mut resp = spawn_server_and_get(NEWNAME);
        assert!(resp.status().is_success());
        let resp_msg: UpdateMessage = resp.json().unwrap();
        assert_eq!(resp_msg, data);

    }
}<commit_msg>Updated error handling for Rocket.<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate rocket_contrib;
extern crate rustyweb;
#[macro_use]
extern crate lazy_static;
extern crate base64;
extern crate serde;
extern crate untrusted;
extern crate ring;
extern crate chrono;

use std::sync::RwLock;

use rocket::State;
use rocket_contrib::{Json};
use rocket::http::Status;

use rustyweb::*;

#[get("/")]
fn hello() -> String {
    format!("Hello world")
}

#[get("/id/<id>")]
fn get_id(id: String, serverdata: State<RwLock<ServerData>>) -> Option<String> {
    if let Some(key) = serverdata.read().unwrap().get_id_key(&id) {
        Some(base64::encode(key))
    } else {
        None
    }
}

#[get("/name/<name>", format = "application/json")]
fn get_name(name: String, serverdata: State<RwLock<ServerData>>) -> Option<Json<UpdateMessage>> {
    if let Some(n) = serverdata.read().unwrap().get_name(&name) {
        Some(Json((*n).clone()))
    } else {
        None
    }
}

#[post("/name/<name>", format = "application/json", data = "<msg>")]
fn post_name(name: String, msg: Json<UpdateMessage>, serverdata: State<RwLock<ServerData>>) -> Result<String, Status> {
    // serverdata.write().unwrap().apply_update_if_valid(&name, &msg.0).map(|_| "ok".to_string())
    match serverdata.write().unwrap().apply_update_if_valid(&name, &msg.0) {
        Ok(_) => Ok("ok".into()),
        Err(v) => Err(Status::Forbidden)
    }
}

fn run(server_data: ServerData, port: u16) {
    let config = rocket::config::Config::build(rocket::config::Environment::Staging)
        .port(port)
        .finalize().expect("Could not create config");

    rocket::custom(config, false)
        .mount("/", routes![hello, get_name, get_id, post_name])
        .manage(RwLock::new(server_data))
        .launch();

}

fn main() {
    let server_data = ServerData::default();
    run(server_data, 8888)
}

#[cfg(test)]
mod tests {
    extern crate reqwest;
    use lazy_static;
    use std::thread;
    use std::io::Read;
    use serde::Serialize;
    use ring::{rand, signature};
    use untrusted;
    use base64;
    use chrono::prelude::*;
    use super::UpdateMessage;

    const UNITTEST_USER: &str = "unittest_user";
    const UNITTEST_NAME: &str = "unittest_name";

    fn start_test_server() {
        use super::ServerData;
        let mut s = ServerData::default();
        let pubkey_bytes = KEYPAIR.public_key_bytes();
        s.add_id(UNITTEST_USER, pubkey_bytes);
        s.update_name(UNITTEST_NAME, &UNITTEST_NAME_VALUE);
        super::run(s, 8888);
    }

    fn generate_keypair() -> signature::Ed25519KeyPair {
        let rng = rand::SystemRandom::new();
        let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
        let keypair = signature::Ed25519KeyPair::from_pkcs8(
            untrusted::Input::from(&pkcs8_bytes)
        ).unwrap();
        keypair
    }

    lazy_static! {
        static ref SERVER_THREAD: thread::JoinHandle<()> = thread::spawn(start_test_server);
        static ref KEYPAIR: signature::Ed25519KeyPair = generate_keypair();
        static ref UNITTEST_NAME_VALUE: UpdateMessage = UpdateMessage::signed_message(&KEYPAIR, UNITTEST_USER, "unittest_value");
    }

    fn spawn_server_and_get(path: &str) -> reqwest::Response {
        lazy_static::initialize(&SERVER_THREAD);
        let new_path = String::from("http://localhost:8888") + path;
        reqwest::get(&new_path).unwrap()
    }

    fn spawn_server_and_post<T: Serialize>(path: &str, json: &T) -> reqwest::Response {
        lazy_static::initialize(&SERVER_THREAD);
        let client = reqwest::Client::new().unwrap();
        let new_path = String::from("http://localhost:8888") + path;
        client.post(&new_path).unwrap()
            .json(json).unwrap()
            .send().unwrap()
    }

    #[test]
    fn test_basic() {
        let mut resp = spawn_server_and_get("/");
        assert!(resp.status().is_success());
        let mut content = String::new();
        resp.read_to_string(&mut content).unwrap();
        assert_eq!(content, "Hello world");
    }

    #[test]
    fn test_id() {
        let mut resp = spawn_server_and_get((String::from("/id/") + UNITTEST_USER).as_str());
        assert!(resp.status().is_success());
        let mut content = String::new();
        resp.read_to_string(&mut content).unwrap();
        let pubkey_bytes = KEYPAIR.public_key_bytes();
        let pubkey_string = base64::encode(pubkey_bytes);
        assert_eq!(content, pubkey_string);
    }

    #[test]
    fn test_get_name() {
        // Test unset name default
        let resp = spawn_server_and_get("/name/test_no_name");
        assert_eq!(resp.status(), reqwest::StatusCode::NotFound);

        // Test set name
        let mut resp = spawn_server_and_get((String::from("/name/") + UNITTEST_NAME).as_str());
        assert!(resp.status().is_success());
        let resp_msg: UpdateMessage = resp.json().unwrap();
        assert_eq!(resp_msg, *UNITTEST_NAME_VALUE);
    }

    #[test]
    fn test_post_name() {
        const NEWNAME: &str = "/name/test_post_name";
        // See that name DNE
        let resp = spawn_server_and_get(NEWNAME);
        assert!(!resp.status().is_success());

        let changed_name = "foo!";
        let data = super::UpdateMessage::signed_message(&KEYPAIR, UNITTEST_USER, changed_name);

        // Change name
        let mut resp = spawn_server_and_post(NEWNAME, &data);
        assert!(resp.status().is_success());
        let mut content = String::new();
        resp.read_to_string(&mut content).unwrap();
        assert_eq!(content, "ok");

        // Test name now that it's been changed
        let mut resp = spawn_server_and_get(NEWNAME);
        assert!(resp.status().is_success());
        let resp_msg: UpdateMessage = resp.json().unwrap();
        assert_eq!(resp_msg, data);

        // Try changing it again with unsigned request
        let baddata = super::UpdateMessage {
            user: UNITTEST_USER.into(),
            utc: Utc::now(),
            signature: "".into(),
            new_contents: "aieeee!".into(),
        };
        let resp = spawn_server_and_post(NEWNAME, &baddata);
        assert!(!resp.status().is_success());

        // Ensure it hasn't changed.
        let mut resp = spawn_server_and_get(NEWNAME);
        assert!(resp.status().is_success());
        let resp_msg: UpdateMessage = resp.json().unwrap();
        assert_eq!(resp_msg, data);
    }
}<|endoftext|>


<commit_before>#[allow(non_snake_case_functions)]
#[allow(unnecessary_parens)]

// Author - Vikram
// Contact - @TheVikO_o
// License - MIT

mod Base64 {

    // Debug Module
    pub mod Debug {
        use std::str;

        // Print bytes as UTF-8 string
        pub fn PrintBytes(data: Vec<u8>) {
            println!("{}", str::from_utf8(data.as_slice()));
        }
    }

    // Encode array of u8 bytes
    pub fn EncodeBytes(source: &[u8])->Vec<u8> {
        let bytes = source;
        let mut i =0;
        let mut output:Vec<u8> = vec![];
        let maxLen = bytes.len();

        while i < maxLen {
            let b1 = (bytes[i] & 0b11111100) >> 2;

            output.push(BaseIndex(b1));

            if (i + 1) < maxLen {
                let b2 = (((bytes[i] & 0b11) << 4) | ((bytes[i+1] & 0b11110000) >> 4));
                output.push(BaseIndex(b2));

                if (i + 2) < maxLen {
                    let b3 = (((bytes[i+1] & 0b1111) << 2) | ((bytes[i+2] & 0b11000000) >> 6));
                    output.push(BaseIndex(b3));

                    let b4 = bytes[i+2] & 0b111111;
                    output.push(BaseIndex(b4));
                } else {
                    let b3 = ((bytes[i+1] & 0b1111) << 2);
                    output.push(BaseIndex(b3));
                    output.push(b'=');
                }

            } else {
                output.push(BaseIndex(((bytes[i] & 0b11) << 4)));
                output.push(b'=');
                output.push(b'=');
            }

            i += 3;
        }

        output
    }

    // Encode str
    pub fn EncodeStr(source: &str) -> Vec<u8> {
        EncodeBytes(source.as_bytes())
    }

    // Decode array of u8 bytes
    pub fn DecodeBytes(source:&[u8]) -> Vec<u8> {
        let bytes = source;
        let mut i =0;
        let mut output:Vec<u8> = vec![];
        let maxLen = bytes.len();

        while i < maxLen {
            let value1:u8 = BaseIndexToByte(bytes[i]);
            let value2:u8 = BaseIndexToByte(bytes[i+1]);
            let value3:u8 = BaseIndexToByte(bytes[i+2]);
            let value4:u8 = BaseIndexToByte(bytes[i+3]);

            let b1: u8 = value1 << 2 | (value2 & 0b00110000) >> 4;
            let b2: u8 = (value2 & 0b1111) << 4 | (value3 & 0b111100) >> 2;
            let b3: u8 = (value3 & 0b11) << 6 | value4;

            output.push(b1);
            output.push(b2);
            output.push(b3);
            i += 4;
        }

        output
    }

    // Decode str
    pub fn DecodeStr(source:&str)->Vec<u8>{
        DecodeBytes(source.as_bytes())
    }

    // Convert byte to base64 rep
    fn BaseIndex(index:u8) -> u8 {
        match index {
            62 => {b'+'}
            63 => {b'/'}
            0..25 => { b'A' + index }
            26..51 => { b'a' + index - 26 }
            _ => { b'0' + index  - 52 }
        }
    }

    // Convert base64 rep to byte
    fn BaseIndexToByte(source:u8)->u8{
        match source {
            b'+' => { 62 }
            b'/' => { 63 }
            b'A'..b'Z' => { source - b'A'}
            b'a'..b'z' => { 26 + source - b'a'}
            b'0'..b'9' => { 52 + source - b'0'}
            _ => { 0 }
        }
    }
}

// Some tests
fn main() {

    let mut encoded = ::Base64::EncodeStr("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut");
    ::Base64::Debug::PrintBytes(encoded);
    let mut decoded = ::Base64::DecodeStr("TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2ljaW5nIGVsaXQsIHNlZCBkbyBlaXVzbW9kIHRlbXBvciBpbmNpZGlkdW50IHV0");
    ::Base64::Debug::PrintBytes(decoded);

    encoded = ::Base64::EncodeStr("ab");
    ::Base64::Debug::PrintBytes(encoded);
    decoded = ::Base64::DecodeStr("YWI=");
    ::Base64::Debug::PrintBytes(decoded);

    encoded = ::Base64::EncodeStr("easure.");
    ::Base64::Debug::PrintBytes(encoded);
    decoded = ::Base64::DecodeStr("ZWFzdXJlLg==");
    ::Base64::Debug::PrintBytes(decoded);

    encoded = ::Base64::EncodeStr("C:\\Users\\ZERO\\AppData\\Local\\Viky Notes\\VikyNotes.xml");
    ::Base64::Debug::PrintBytes(encoded);
    decoded = ::Base64::DecodeStr("QzpcVXNlcnNcWkVST1xBcHBEYXRhXExvY2FsXFZpa3kgTm90ZXNcVmlreU5vdGVzLnhtbA==");
    ::Base64::Debug::PrintBytes(decoded);

    encoded = ::Base64::EncodeStr("C:\\Users\\ZERO\\AppData\\Local\\Viky Notes\\VikyNotes.xml");
    ::Base64::Debug::PrintBytes(encoded);
    decoded = ::Base64::DecodeStr("QzpcVXNlcnNcWkVST1xBcHBEYXRhXExvY2FsXFZpa3kgTm90ZXNcVmlreU5vdGVzLnhtbA==");
    ::Base64::Debug::PrintBytes(decoded);
}<commit_msg>Handle invalid encoded data<commit_after>#[allow(non_snake_case_functions)]
#[allow(unnecessary_parens)]

// Author - Vikram
// Contact - @TheVikO_o
// License - MIT

mod Base64 {

    // Debug Module
    pub mod Debug {
        use std::str;

        // Print bytes as UTF-8 string
        pub fn PrintBytes(data: Vec<u8>) {
            println!("{}", str::from_utf8(data.as_slice()));
        }
    }

    // Encode array of u8 bytes
    pub fn EncodeBytes(source: &[u8])->Vec<u8> {
        let bytes = source;
        let mut i =0;
        let mut output:Vec<u8> = vec![];
        let maxLen = bytes.len();

        while i < maxLen {
            let b1 = (bytes[i] & 0b11111100) >> 2;

            output.push(BaseIndex(b1));

            if (i + 1) < maxLen {
                let b2 = (((bytes[i] & 0b11) << 4) | ((bytes[i+1] & 0b11110000) >> 4));
                output.push(BaseIndex(b2));

                if (i + 2) < maxLen {
                    let b3 = (((bytes[i+1] & 0b1111) << 2) | ((bytes[i+2] & 0b11000000) >> 6));
                    output.push(BaseIndex(b3));

                    let b4 = bytes[i+2] & 0b111111;
                    output.push(BaseIndex(b4));
                } else {
                    let b3 = ((bytes[i+1] & 0b1111) << 2);
                    output.push(BaseIndex(b3));
                    output.push(b'=');
                }

            } else {
                output.push(BaseIndex(((bytes[i] & 0b11) << 4)));
                output.push(b'=');
                output.push(b'=');
            }

            i += 3;
        }

        output
    }

    // Encode str
    pub fn EncodeStr(source: &str) -> Vec<u8> {
        EncodeBytes(source.as_bytes())
    }

    // Decode array of u8 bytes
    pub fn DecodeBytes(source:&[u8]) -> Vec<u8> {

        let bytes = source;
        let mut i =0;
        let mut output:Vec<u8> = vec![];
        let maxLen = bytes.len();

        if source.len() % 4 != 0 {
            return output;
        }

        while i < maxLen {
            let value1:u8 = BaseIndexToByte(bytes[i]);
            let value2:u8 = BaseIndexToByte(bytes[i+1]);
            let value3:u8 = BaseIndexToByte(bytes[i+2]);
            let value4:u8 = BaseIndexToByte(bytes[i+3]);

            let b1: u8 = value1 << 2 | (value2 & 0b00110000) >> 4;
            let b2: u8 = (value2 & 0b1111) << 4 | (value3 & 0b111100) >> 2;
            let b3: u8 = (value3 & 0b11) << 6 | value4;

            output.push(b1);
            output.push(b2);
            output.push(b3);
            i += 4;
        }

        output
    }

    // Decode str
    pub fn DecodeStr(source:&str)->Vec<u8>{
        DecodeBytes(source.as_bytes())
    }

    // Convert byte to base64 rep
    fn BaseIndex(index:u8) -> u8 {
        match index {
            62 => {b'+'}
            63 => {b'/'}
            0..25 => { b'A' + index }
            26..51 => { b'a' + index - 26 }
            _ => { b'0' + index  - 52 }
        }
    }

    // Convert base64 rep to byte
    fn BaseIndexToByte(source:u8)->u8{
        match source {
            b'+' => { 62 }
            b'/' => { 63 }
            b'A'..b'Z' => { source - b'A'}
            b'a'..b'z' => { 26 + source - b'a'}
            b'0'..b'9' => { 52 + source - b'0'}
            _ => { 0 }
        }
    }
}

// Some tests
fn main() {

    let mut encoded = ::Base64::EncodeStr("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut");
    ::Base64::Debug::PrintBytes(encoded);
    let mut decoded = ::Base64::DecodeStr("TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2ljaW5nIGVsaXQsIHNlZCBkbyBlaXVzbW9kIHRlbXBvciBpbmNpZGlkdW50IHV0");
    ::Base64::Debug::PrintBytes(decoded);

    encoded = ::Base64::EncodeStr("ab");
    ::Base64::Debug::PrintBytes(encoded);
    decoded = ::Base64::DecodeStr("YWI=");
    ::Base64::Debug::PrintBytes(decoded);

    encoded = ::Base64::EncodeStr("easure.");
    ::Base64::Debug::PrintBytes(encoded);
    decoded = ::Base64::DecodeStr("ZWFzdXJlLg==");
    ::Base64::Debug::PrintBytes(decoded);

    encoded = ::Base64::EncodeStr("C:\\Users\\AppData\\Local\\Viky Notes\\VikyNotes.exe");
    ::Base64::Debug::PrintBytes(encoded);
    decoded = ::Base64::DecodeStr("QzpcVXNlcnNcQXBwRGF0YVxMb2NhbFxWaWt5IE5vdGVzXFZpa3lOb3Rlcy5leGU=");
    ::Base64::Debug::PrintBytes(decoded);

    decoded = ::Base64::DecodeStr("TW");
    ::Base64::Debug::PrintBytes(decoded);
}<|endoftext|>