diff options
| author | Valentin <[email protected]> | 2018-06-15 18:57:24 +0200 |
|---|---|---|
| committer | FenrirWolf <[email protected]> | 2018-06-15 10:57:24 -0600 |
| commit | f2a90174bb36b9ad528e863ab34c02ebce002b02 (patch) | |
| tree | 959e8d67883d3a89e179b3549b1f30d28e51a87c /ctr-std/src/sys/wasm | |
| parent | Merge pull request #68 from linouxis9/master (diff) | |
| download | ctru-rs-f2a90174bb36b9ad528e863ab34c02ebce002b02.tar.xz ctru-rs-f2a90174bb36b9ad528e863ab34c02ebce002b02.zip | |
Update for latest nightly 2018-06-09 (#70)
* Update for latest nightly 2018-06-09
* We now have a proper horizon os and sys modules in libstd
Diffstat (limited to 'ctr-std/src/sys/wasm')
| -rw-r--r-- | ctr-std/src/sys/wasm/args.rs | 62 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/backtrace.rs | 37 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/cmath.rs | 119 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/condvar.rs | 43 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/env.rs | 19 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/fs.rs | 304 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/memchr.rs | 11 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/mod.rs | 314 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/mutex.rs | 79 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/net.rs | 337 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/os.rs | 112 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/os_str.rs | 189 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/path.rs | 29 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/pipe.rs | 35 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/process.rs | 162 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/rwlock.rs | 82 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/stack_overflow.rs | 23 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/stdio.rs | 75 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/thread.rs | 50 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/thread_local.rs | 50 | ||||
| -rw-r--r-- | ctr-std/src/sys/wasm/time.rs | 57 |
21 files changed, 2189 insertions, 0 deletions
diff --git a/ctr-std/src/sys/wasm/args.rs b/ctr-std/src/sys/wasm/args.rs new file mode 100644 index 0000000..b3c6b67 --- /dev/null +++ b/ctr-std/src/sys/wasm/args.rs @@ -0,0 +1,62 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi::OsString; +use marker::PhantomData; +use vec; +use sys::ArgsSysCall; + +pub unsafe fn init(_argc: isize, _argv: *const *const u8) { + // On wasm these should always be null, so there's nothing for us to do here +} + +pub unsafe fn cleanup() { +} + +pub fn args() -> Args { + let v = ArgsSysCall::perform(); + Args { + iter: v.into_iter(), + _dont_send_or_sync_me: PhantomData, + } +} + +pub struct Args { + iter: vec::IntoIter<OsString>, + _dont_send_or_sync_me: PhantomData<*mut ()>, +} + +impl Args { + pub fn inner_debug(&self) -> &[OsString] { + self.iter.as_slice() + } +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option<OsString> { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option<OsString> { + self.iter.next_back() + } +} diff --git a/ctr-std/src/sys/wasm/backtrace.rs b/ctr-std/src/sys/wasm/backtrace.rs new file mode 100644 index 0000000..9a8c48f --- /dev/null +++ b/ctr-std/src/sys/wasm/backtrace.rs @@ -0,0 +1,37 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use sys::unsupported; +use sys_common::backtrace::Frame; + +pub struct BacktraceContext; + +pub fn unwind_backtrace(_frames: &mut [Frame]) + -> io::Result<(usize, BacktraceContext)> +{ + unsupported() +} + +pub fn resolve_symname<F>(_frame: Frame, + _callback: F, + _: &BacktraceContext) -> io::Result<()> + where F: FnOnce(Option<&str>) -> io::Result<()> +{ + unsupported() +} + +pub fn foreach_symbol_fileline<F>(_: Frame, + _: F, + _: &BacktraceContext) -> io::Result<bool> + where F: FnMut(&[u8], u32) -> io::Result<()> +{ + unsupported() +} diff --git a/ctr-std/src/sys/wasm/cmath.rs b/ctr-std/src/sys/wasm/cmath.rs new file mode 100644 index 0000000..87ac209 --- /dev/null +++ b/ctr-std/src/sys/wasm/cmath.rs @@ -0,0 +1,119 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[inline] +pub unsafe fn cbrtf(n: f32) -> f32 { + f64::cbrt(n as f64) as f32 +} + +#[inline] +pub unsafe fn expm1f(n: f32) -> f32 { + f64::exp_m1(n as f64) as f32 +} + +#[inline] +#[allow(deprecated)] +pub unsafe fn fdimf(a: f32, b: f32) -> f32 { + f64::abs_sub(a as f64, b as f64) as f32 +} + +#[inline] +pub unsafe fn log1pf(n: f32) -> f32 { + f64::ln_1p(n as f64) as f32 +} + +#[inline] +pub unsafe fn hypotf(x: f32, y: f32) -> f32 { + f64::hypot(x as f64, y as f64) as f32 +} + +#[inline] +pub unsafe fn acosf(n: f32) -> f32 { + f64::acos(n as f64) as f32 +} + +#[inline] +pub unsafe fn asinf(n: f32) -> f32 { + f64::asin(n as f64) as f32 +} + +#[inline] +pub unsafe fn atan2f(n: f32, b: f32) -> f32 { + f64::atan2(n as f64, b as f64) as f32 +} + +#[inline] +pub unsafe fn atanf(n: f32) -> f32 { + f64::atan(n as f64) as f32 +} + +#[inline] +pub unsafe fn coshf(n: f32) -> f32 { + f64::cosh(n as f64) as f32 +} + +#[inline] +pub unsafe fn sinhf(n: f32) -> f32 { + f64::sinh(n as f64) as f32 +} + +#[inline] +pub unsafe fn tanf(n: f32) -> f32 { + f64::tan(n as f64) as f32 +} + +#[inline] +pub unsafe fn tanhf(n: f32) -> f32 { + f64::tanh(n as f64) as f32 +} + +// Right now all these functions, the f64 version of the functions above, all +// shell out to random names. These names aren't actually defined anywhere, per +// se, but we need this to compile somehow. +// +// The idea with this is that when you're using wasm then, for now, we have no +// way of providing an implementation of these which delegates to a "correct" +// implementation. For example most wasm applications probably just want to +// delegate to the javascript `Math` object and its related functions, but wasm +// doesn't currently have the ability to seamlessly do that (when you +// instantiate a module you have to set that up). +// +// As a result these are just defined here with "hopefully helpful" names. The +// symbols won't ever be needed or show up unless these functions are called, +// and hopefully when they're called the errors are self-explanatory enough to +// figure out what's going on. + +extern { + #[link_name = "Math_acos"] + pub fn acos(n: f64) -> f64; + #[link_name = "Math_asin"] + pub fn asin(n: f64) -> f64; + #[link_name = "Math_atan"] + pub fn atan(n: f64) -> f64; + #[link_name = "Math_atan2"] + pub fn atan2(a: f64, b: f64) -> f64; + #[link_name = "Math_cbrt"] + pub fn cbrt(n: f64) -> f64; + #[link_name = "Math_cosh"] + pub fn cosh(n: f64) -> f64; + #[link_name = "Math_expm1"] + pub fn expm1(n: f64) -> f64; + pub fn fdim(a: f64, b: f64) -> f64; + #[link_name = "Math_log1p"] + pub fn log1p(n: f64) -> f64; + #[link_name = "Math_sinh"] + pub fn sinh(n: f64) -> f64; + #[link_name = "Math_tan"] + pub fn tan(n: f64) -> f64; + #[link_name = "Math_tanh"] + pub fn tanh(n: f64) -> f64; + #[link_name = "Math_hypot"] + pub fn hypot(x: f64, y: f64) -> f64; +} diff --git a/ctr-std/src/sys/wasm/condvar.rs b/ctr-std/src/sys/wasm/condvar.rs new file mode 100644 index 0000000..afa7afe --- /dev/null +++ b/ctr-std/src/sys/wasm/condvar.rs @@ -0,0 +1,43 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use sys::mutex::Mutex; +use time::Duration; + +pub struct Condvar { } + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { } + } + + #[inline] + pub unsafe fn init(&mut self) {} + + #[inline] + pub unsafe fn notify_one(&self) { + } + + #[inline] + pub unsafe fn notify_all(&self) { + } + + pub unsafe fn wait(&self, _mutex: &Mutex) { + panic!("can't block with web assembly") + } + + pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + panic!("can't block with web assembly"); + } + + #[inline] + pub unsafe fn destroy(&self) { + } +} diff --git a/ctr-std/src/sys/wasm/env.rs b/ctr-std/src/sys/wasm/env.rs new file mode 100644 index 0000000..1422042 --- /dev/null +++ b/ctr-std/src/sys/wasm/env.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod os { + pub const FAMILY: &'static str = ""; + pub const OS: &'static str = ""; + pub const DLL_PREFIX: &'static str = ""; + pub const DLL_SUFFIX: &'static str = ".wasm"; + pub const DLL_EXTENSION: &'static str = "wasm"; + pub const EXE_SUFFIX: &'static str = ".wasm"; + pub const EXE_EXTENSION: &'static str = "wasm"; +} diff --git a/ctr-std/src/sys/wasm/fs.rs b/ctr-std/src/sys/wasm/fs.rs new file mode 100644 index 0000000..b3c70a6 --- /dev/null +++ b/ctr-std/src/sys/wasm/fs.rs @@ -0,0 +1,304 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi::OsString; +use fmt; +use hash::{Hash, Hasher}; +use io::{self, SeekFrom}; +use path::{Path, PathBuf}; +use sys::time::SystemTime; +use sys::{unsupported, Void}; + +pub struct File(Void); + +pub struct FileAttr(Void); + +pub struct ReadDir(Void); + +pub struct DirEntry(Void); + +#[derive(Clone, Debug)] +pub struct OpenOptions { } + +pub struct FilePermissions(Void); + +pub struct FileType(Void); + +#[derive(Debug)] +pub struct DirBuilder { } + +impl FileAttr { + pub fn size(&self) -> u64 { + match self.0 {} + } + + pub fn perm(&self) -> FilePermissions { + match self.0 {} + } + + pub fn file_type(&self) -> FileType { + match self.0 {} + } + + pub fn modified(&self) -> io::Result<SystemTime> { + match self.0 {} + } + + pub fn accessed(&self) -> io::Result<SystemTime> { + match self.0 {} + } + + pub fn created(&self) -> io::Result<SystemTime> { + match self.0 {} + } +} + +impl Clone for FileAttr { + fn clone(&self) -> FileAttr { + match self.0 {} + } +} + +impl FilePermissions { + pub fn readonly(&self) -> bool { + match self.0 {} + } + + pub fn set_readonly(&mut self, _readonly: bool) { + match self.0 {} + } +} + +impl Clone for FilePermissions { + fn clone(&self) -> FilePermissions { + match self.0 {} + } +} + +impl PartialEq for FilePermissions { + fn eq(&self, _other: &FilePermissions) -> bool { + match self.0 {} + } +} + +impl Eq for FilePermissions { +} + +impl fmt::Debug for FilePermissions { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl FileType { + pub fn is_dir(&self) -> bool { + match self.0 {} + } + + pub fn is_file(&self) -> bool { + match self.0 {} + } + + pub fn is_symlink(&self) -> bool { + match self.0 {} + } +} + +impl Clone for FileType { + fn clone(&self) -> FileType { + match self.0 {} + } +} + +impl Copy for FileType {} + +impl PartialEq for FileType { + fn eq(&self, _other: &FileType) -> bool { + match self.0 {} + } +} + +impl Eq for FileType { +} + +impl Hash for FileType { + fn hash<H: Hasher>(&self, _h: &mut H) { + match self.0 {} + } +} + +impl fmt::Debug for FileType { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl fmt::Debug for ReadDir { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl Iterator for ReadDir { + type Item = io::Result<DirEntry>; + + fn next(&mut self) -> Option<io::Result<DirEntry>> { + match self.0 {} + } +} + +impl DirEntry { + pub fn path(&self) -> PathBuf { + match self.0 {} + } + + pub fn file_name(&self) -> OsString { + match self.0 {} + } + + pub fn metadata(&self) -> io::Result<FileAttr> { + match self.0 {} + } + + pub fn file_type(&self) -> io::Result<FileType> { + match self.0 {} + } +} + +impl OpenOptions { + pub fn new() -> OpenOptions { + OpenOptions { } + } + + pub fn read(&mut self, _read: bool) { } + pub fn write(&mut self, _write: bool) { } + pub fn append(&mut self, _append: bool) { } + pub fn truncate(&mut self, _truncate: bool) { } + pub fn create(&mut self, _create: bool) { } + pub fn create_new(&mut self, _create_new: bool) { } +} + +impl File { + pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> { + unsupported() + } + + pub fn file_attr(&self) -> io::Result<FileAttr> { + match self.0 {} + } + + pub fn fsync(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn datasync(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn truncate(&self, _size: u64) -> io::Result<()> { + match self.0 {} + } + + pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn write(&self, _buf: &[u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn flush(&self) -> io::Result<()> { + match self.0 {} + } + + pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result<File> { + match self.0 {} + } + + pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { + match self.0 {} + } + + pub fn diverge(&self) -> ! { + match self.0 {} + } +} + +impl DirBuilder { + pub fn new() -> DirBuilder { + DirBuilder { } + } + + pub fn mkdir(&self, _p: &Path) -> io::Result<()> { + unsupported() + } +} + +impl fmt::Debug for File { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub fn readdir(_p: &Path) -> io::Result<ReadDir> { + unsupported() +} + +pub fn unlink(_p: &Path) -> io::Result<()> { + unsupported() +} + +pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + +pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> { + match perm.0 {} +} + +pub fn rmdir(_p: &Path) -> io::Result<()> { + unsupported() +} + +pub fn remove_dir_all(_path: &Path) -> io::Result<()> { + unsupported() +} + +pub fn readlink(_p: &Path) -> io::Result<PathBuf> { + unsupported() +} + +pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { + unsupported() +} + +pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { + unsupported() +} + +pub fn stat(_p: &Path) -> io::Result<FileAttr> { + unsupported() +} + +pub fn lstat(_p: &Path) -> io::Result<FileAttr> { + unsupported() +} + +pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> { + unsupported() +} + +pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> { + unsupported() +} diff --git a/ctr-std/src/sys/wasm/memchr.rs b/ctr-std/src/sys/wasm/memchr.rs new file mode 100644 index 0000000..964e359 --- /dev/null +++ b/ctr-std/src/sys/wasm/memchr.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use core::slice::memchr::{memchr, memrchr}; diff --git a/ctr-std/src/sys/wasm/mod.rs b/ctr-std/src/sys/wasm/mod.rs new file mode 100644 index 0000000..c02e5e8 --- /dev/null +++ b/ctr-std/src/sys/wasm/mod.rs @@ -0,0 +1,314 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! System bindings for the wasm/web platform +//! +//! This module contains the facade (aka platform-specific) implementations of +//! OS level functionality for wasm. Note that this wasm is *not* the emscripten +//! wasm, so we have no runtime here. +//! +//! This is all super highly experimental and not actually intended for +//! wide/production use yet, it's still all in the experimental category. This +//! will likely change over time. +//! +//! Currently all functions here are basically stubs that immediately return +//! errors. The hope is that with a portability lint we can turn actually just +//! remove all this and just omit parts of the standard library if we're +//! compiling for wasm. That way it's a compile time error for something that's +//! guaranteed to be a runtime error! + +use io; +use os::raw::c_char; +use ptr; +use sys::os_str::Buf; +use sys_common::{AsInner, FromInner}; +use ffi::{OsString, OsStr}; +use time::Duration; + +pub mod args; +#[cfg(feature = "backtrace")] +pub mod backtrace; +pub mod cmath; +pub mod condvar; +pub mod env; +pub mod fs; +pub mod memchr; +pub mod mutex; +pub mod net; +pub mod os; +pub mod os_str; +pub mod path; +pub mod pipe; +pub mod process; +pub mod rwlock; +pub mod stack_overflow; +pub mod thread; +pub mod thread_local; +pub mod time; +pub mod stdio; + +#[cfg(not(test))] +pub fn init() { +} + +pub fn unsupported<T>() -> io::Result<T> { + Err(unsupported_err()) +} + +pub fn unsupported_err() -> io::Error { + io::Error::new(io::ErrorKind::Other, + "operation not supported on wasm yet") +} + +pub fn decode_error_kind(_code: i32) -> io::ErrorKind { + io::ErrorKind::Other +} + +// This enum is used as the storage for a bunch of types which can't actually +// exist. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum Void {} + +pub unsafe fn strlen(mut s: *const c_char) -> usize { + let mut n = 0; + while *s != 0 { + n += 1; + s = s.offset(1); + } + return n +} + +pub unsafe fn abort_internal() -> ! { + ExitSysCall::perform(1) +} + +// We don't have randomness yet, but I totally used a random number generator to +// generate these numbers. +// +// More seriously though this is just for DOS protection in hash maps. It's ok +// if we don't do that on wasm just yet. +pub fn hashmap_random_keys() -> (u64, u64) { + (1, 2) +} + +// Implement a minimal set of system calls to enable basic IO +pub enum SysCallIndex { + Read = 0, + Write = 1, + Exit = 2, + Args = 3, + GetEnv = 4, + SetEnv = 5, + Time = 6, +} + +#[repr(C)] +pub struct ReadSysCall { + fd: usize, + ptr: *mut u8, + len: usize, + result: usize, +} + +impl ReadSysCall { + pub fn perform(fd: usize, buffer: &mut [u8]) -> usize { + let mut call_record = ReadSysCall { + fd, + len: buffer.len(), + ptr: buffer.as_mut_ptr(), + result: 0 + }; + if unsafe { syscall(SysCallIndex::Read, &mut call_record) } { + call_record.result + } else { + 0 + } + } +} + +#[repr(C)] +pub struct WriteSysCall { + fd: usize, + ptr: *const u8, + len: usize, +} + +impl WriteSysCall { + pub fn perform(fd: usize, buffer: &[u8]) { + let mut call_record = WriteSysCall { + fd, + len: buffer.len(), + ptr: buffer.as_ptr() + }; + unsafe { syscall(SysCallIndex::Write, &mut call_record); } + } +} + +#[repr(C)] +pub struct ExitSysCall { + code: usize, +} + +impl ExitSysCall { + pub fn perform(code: usize) -> ! { + let mut call_record = ExitSysCall { + code + }; + unsafe { + syscall(SysCallIndex::Exit, &mut call_record); + ::intrinsics::abort(); + } + } +} + +fn receive_buffer<E, F: FnMut(&mut [u8]) -> Result<usize, E>>(estimate: usize, mut f: F) + -> Result<Vec<u8>, E> +{ + let mut buffer = vec![0; estimate]; + loop { + let result = f(&mut buffer)?; + if result <= buffer.len() { + buffer.truncate(result); + break; + } + buffer.resize(result, 0); + } + Ok(buffer) +} + +#[repr(C)] +pub struct ArgsSysCall { + ptr: *mut u8, + len: usize, + result: usize +} + +impl ArgsSysCall { + pub fn perform() -> Vec<OsString> { + receive_buffer(1024, |buffer| -> Result<usize, !> { + let mut call_record = ArgsSysCall { + len: buffer.len(), + ptr: buffer.as_mut_ptr(), + result: 0 + }; + if unsafe { syscall(SysCallIndex::Args, &mut call_record) } { + Ok(call_record.result) + } else { + Ok(0) + } + }) + .unwrap() + .split(|b| *b == 0) + .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() })) + .collect() + } +} + +#[repr(C)] +pub struct GetEnvSysCall { + key_ptr: *const u8, + key_len: usize, + value_ptr: *mut u8, + value_len: usize, + result: usize +} + +impl GetEnvSysCall { + pub fn perform(key: &OsStr) -> Option<OsString> { + let key_buf = &AsInner::as_inner(key).inner; + receive_buffer(64, |buffer| { + let mut call_record = GetEnvSysCall { + key_len: key_buf.len(), + key_ptr: key_buf.as_ptr(), + value_len: buffer.len(), + value_ptr: buffer.as_mut_ptr(), + result: !0usize + }; + if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } { + if call_record.result == !0usize { + Err(()) + } else { + Ok(call_record.result) + } + } else { + Err(()) + } + }).ok().map(|s| { + FromInner::from_inner(Buf { inner: s }) + }) + } +} + +#[repr(C)] +pub struct SetEnvSysCall { + key_ptr: *const u8, + key_len: usize, + value_ptr: *const u8, + value_len: usize +} + +impl SetEnvSysCall { + pub fn perform(key: &OsStr, value: Option<&OsStr>) { + let key_buf = &AsInner::as_inner(key).inner; + let value_buf = value.map(|v| &AsInner::as_inner(v).inner); + let mut call_record = SetEnvSysCall { + key_len: key_buf.len(), + key_ptr: key_buf.as_ptr(), + value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize), + value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null()) + }; + unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); } + } +} + +pub enum TimeClock { + Monotonic = 0, + System = 1, +} + +#[repr(C)] +pub struct TimeSysCall { + clock: usize, + secs_hi: usize, + secs_lo: usize, + nanos: usize +} + +impl TimeSysCall { + pub fn perform(clock: TimeClock) -> Duration { + let mut call_record = TimeSysCall { + clock: clock as usize, + secs_hi: 0, + secs_lo: 0, + nanos: 0 + }; + if unsafe { syscall(SysCallIndex::Time, &mut call_record) } { + Duration::new( + ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64), + call_record.nanos as u32 + ) + } else { + panic!("Time system call is not implemented by WebAssembly host"); + } + } +} + +unsafe fn syscall<T>(index: SysCallIndex, data: &mut T) -> bool { + #[cfg(feature = "wasm_syscall")] + extern { + #[no_mangle] + fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize; + } + + #[cfg(not(feature = "wasm_syscall"))] + unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 } + + rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0 +} diff --git a/ctr-std/src/sys/wasm/mutex.rs b/ctr-std/src/sys/wasm/mutex.rs new file mode 100644 index 0000000..4197bdc --- /dev/null +++ b/ctr-std/src/sys/wasm/mutex.rs @@ -0,0 +1,79 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cell::UnsafeCell; + +pub struct Mutex { + locked: UnsafeCell<bool>, +} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} // no threads on wasm + +impl Mutex { + pub const fn new() -> Mutex { + Mutex { locked: UnsafeCell::new(false) } + } + + #[inline] + pub unsafe fn init(&mut self) { + } + + #[inline] + pub unsafe fn lock(&self) { + let locked = self.locked.get(); + assert!(!*locked, "cannot recursively acquire mutex"); + *locked = true; + } + + #[inline] + pub unsafe fn unlock(&self) { + *self.locked.get() = false; + } + + #[inline] + pub unsafe fn try_lock(&self) -> bool { + let locked = self.locked.get(); + if *locked { + false + } else { + *locked = true; + true + } + } + + #[inline] + pub unsafe fn destroy(&self) { + } +} + +// All empty stubs because wasm has no threads yet, so lock acquisition always +// succeeds. +pub struct ReentrantMutex { +} + +impl ReentrantMutex { + pub unsafe fn uninitialized() -> ReentrantMutex { + ReentrantMutex { } + } + + pub unsafe fn init(&mut self) {} + + pub unsafe fn lock(&self) {} + + #[inline] + pub unsafe fn try_lock(&self) -> bool { + true + } + + pub unsafe fn unlock(&self) {} + + pub unsafe fn destroy(&self) {} +} diff --git a/ctr-std/src/sys/wasm/net.rs b/ctr-std/src/sys/wasm/net.rs new file mode 100644 index 0000000..e7476ab --- /dev/null +++ b/ctr-std/src/sys/wasm/net.rs @@ -0,0 +1,337 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use fmt; +use io; +use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr}; +use time::Duration; +use sys::{unsupported, Void}; + +pub struct TcpStream(Void); + +impl TcpStream { + pub fn connect(_: &SocketAddr) -> io::Result<TcpStream> { + unsupported() + } + + pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> { + unsupported() + } + + pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> { + match self.0 {} + } + + pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> { + match self.0 {} + } + + pub fn read_timeout(&self) -> io::Result<Option<Duration>> { + match self.0 {} + } + + pub fn write_timeout(&self) -> io::Result<Option<Duration>> { + match self.0 {} + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn read(&self, _: &mut [u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn write(&self, _: &[u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn peer_addr(&self) -> io::Result<SocketAddr> { + match self.0 {} + } + + pub fn socket_addr(&self) -> io::Result<SocketAddr> { + match self.0 {} + } + + pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result<TcpStream> { + match self.0 {} + } + + pub fn set_nodelay(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn nodelay(&self) -> io::Result<bool> { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result<u32> { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result<Option<io::Error>> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for TcpStream { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub struct TcpListener(Void); + +impl TcpListener { + pub fn bind(_: &SocketAddr) -> io::Result<TcpListener> { + unsupported() + } + + pub fn socket_addr(&self) -> io::Result<SocketAddr> { + match self.0 {} + } + + pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result<TcpListener> { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result<u32> { + match self.0 {} + } + + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn only_v6(&self) -> io::Result<bool> { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result<Option<io::Error>> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for TcpListener { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub struct UdpSocket(Void); + +impl UdpSocket { + pub fn bind(_: &SocketAddr) -> io::Result<UdpSocket> { + unsupported() + } + + pub fn socket_addr(&self) -> io::Result<SocketAddr> { + match self.0 {} + } + + pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + match self.0 {} + } + + pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + match self.0 {} + } + + pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> { + match self.0 {} + } + + pub fn duplicate(&self) -> io::Result<UdpSocket> { + match self.0 {} + } + + pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> { + match self.0 {} + } + + pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> { + match self.0 {} + } + + pub fn read_timeout(&self) -> io::Result<Option<Duration>> { + match self.0 {} + } + + pub fn write_timeout(&self) -> io::Result<Option<Duration>> { + match self.0 {} + } + + pub fn set_broadcast(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn broadcast(&self) -> io::Result<bool> { + match self.0 {} + } + + pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_loop_v4(&self) -> io::Result<bool> { + match self.0 {} + } + + pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_ttl_v4(&self) -> io::Result<u32> { + match self.0 {} + } + + pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn multicast_loop_v6(&self) -> io::Result<bool> { + match self.0 {} + } + + pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) + -> io::Result<()> { + match self.0 {} + } + + pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) + -> io::Result<()> { + match self.0 {} + } + + pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) + -> io::Result<()> { + match self.0 {} + } + + pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) + -> io::Result<()> { + match self.0 {} + } + + pub fn set_ttl(&self, _: u32) -> io::Result<()> { + match self.0 {} + } + + pub fn ttl(&self) -> io::Result<u32> { + match self.0 {} + } + + pub fn take_error(&self) -> io::Result<Option<io::Error>> { + match self.0 {} + } + + pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { + match self.0 {} + } + + pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn send(&self, _: &[u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn connect(&self, _: &SocketAddr) -> io::Result<()> { + match self.0 {} + } +} + +impl fmt::Debug for UdpSocket { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +pub struct LookupHost(Void); + +impl Iterator for LookupHost { + type Item = SocketAddr; + fn next(&mut self) -> Option<SocketAddr> { + match self.0 {} + } +} + +pub fn lookup_host(_: &str) -> io::Result<LookupHost> { + unsupported() +} + +#[allow(bad_style)] +pub mod netc { + pub const AF_INET: u8 = 0; + pub const AF_INET6: u8 = 1; + pub type sa_family_t = u8; + + #[derive(Copy, Clone)] + pub struct in_addr { + pub s_addr: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: u16, + pub sin_addr: in_addr, + } + + #[derive(Copy, Clone)] + pub struct in6_addr { + pub s6_addr: [u8; 16], + } + + #[derive(Copy, Clone)] + pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: u16, + pub sin6_addr: in6_addr, + pub sin6_flowinfo: u32, + pub sin6_scope_id: u32, + } + + #[derive(Copy, Clone)] + pub struct sockaddr { + } + + pub type socklen_t = usize; +} diff --git a/ctr-std/src/sys/wasm/os.rs b/ctr-std/src/sys/wasm/os.rs new file mode 100644 index 0000000..23ca175 --- /dev/null +++ b/ctr-std/src/sys/wasm/os.rs @@ -0,0 +1,112 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use error::Error as StdError; +use ffi::{OsString, OsStr}; +use fmt; +use io; +use path::{self, PathBuf}; +use str; +use sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall}; + +pub fn errno() -> i32 { + 0 +} + +pub fn error_string(_errno: i32) -> String { + format!("operation successful") +} + +pub fn getcwd() -> io::Result<PathBuf> { + unsupported() +} + +pub fn chdir(_: &path::Path) -> io::Result<()> { + unsupported() +} + +pub struct SplitPaths<'a>(&'a Void); + +pub fn split_paths(_unparsed: &OsStr) -> SplitPaths { + panic!("unsupported") +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option<PathBuf> { + match *self.0 {} + } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError> + where I: Iterator<Item=T>, T: AsRef<OsStr> +{ + Err(JoinPathsError) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "not supported on wasm yet".fmt(f) + } +} + +impl StdError for JoinPathsError { + fn description(&self) -> &str { + "not supported on wasm yet" + } +} + +pub fn current_exe() -> io::Result<PathBuf> { + unsupported() +} + +pub struct Env(Void); + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + match self.0 {} + } +} + +pub fn env() -> Env { + panic!("not supported on web assembly") +} + +pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { + Ok(GetEnvSysCall::perform(k)) +} + +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + Ok(SetEnvSysCall::perform(k, Some(v))) +} + +pub fn unsetenv(k: &OsStr) -> io::Result<()> { + Ok(SetEnvSysCall::perform(k, None)) +} + +pub fn temp_dir() -> PathBuf { + panic!("no filesystem on wasm") +} + +pub fn home_dir() -> Option<PathBuf> { + None +} + +pub fn exit(_code: i32) -> ! { + ExitSysCall::perform(_code as isize as usize) +} + +pub fn getpid() -> u32 { + panic!("no pids on wasm") +} diff --git a/ctr-std/src/sys/wasm/os_str.rs b/ctr-std/src/sys/wasm/os_str.rs new file mode 100644 index 0000000..e0da5bd --- /dev/null +++ b/ctr-std/src/sys/wasm/os_str.rs @@ -0,0 +1,189 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// The underlying OsString/OsStr implementation on Unix systems: just +/// a `Vec<u8>`/`[u8]`. + +use borrow::Cow; +use fmt; +use str; +use mem; +use rc::Rc; +use sync::Arc; +use sys_common::{AsInner, IntoInner}; +use sys_common::bytestring::debug_fmt_bytestring; +use core::str::lossy::Utf8Lossy; + +#[derive(Clone, Hash)] +pub struct Buf { + pub inner: Vec<u8> +} + +pub struct Slice { + pub inner: [u8] +} + +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + debug_fmt_bytestring(&self.inner, formatter) + } +} + +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) + } +} + +impl IntoInner<Vec<u8>> for Buf { + fn into_inner(self) -> Vec<u8> { + self.inner + } +} + +impl AsInner<[u8]> for Buf { + fn as_inner(&self) -> &[u8] { + &self.inner + } +} + + +impl Buf { + pub fn from_string(s: String) -> Buf { + Buf { inner: s.into_bytes() } + } + + #[inline] + pub fn with_capacity(capacity: usize) -> Buf { + Buf { + inner: Vec::with_capacity(capacity) + } + } + + #[inline] + pub fn clear(&mut self) { + self.inner.clear() + } + + #[inline] + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.inner.reserve(additional) + } + + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.inner.reserve_exact(additional) + } + + #[inline] + pub fn shrink_to_fit(&mut self) { + self.inner.shrink_to_fit() + } + + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + + pub fn as_slice(&self) -> &Slice { + unsafe { mem::transmute(&*self.inner) } + } + + pub fn into_string(self) -> Result<String, Buf> { + String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } ) + } + + pub fn push_slice(&mut self, s: &Slice) { + self.inner.extend_from_slice(&s.inner) + } + + #[inline] + pub fn into_box(self) -> Box<Slice> { + unsafe { mem::transmute(self.inner.into_boxed_slice()) } + } + + #[inline] + pub fn from_box(boxed: Box<Slice>) -> Buf { + let inner: Box<[u8]> = unsafe { mem::transmute(boxed) }; + Buf { inner: inner.into_vec() } + } + + #[inline] + pub fn into_arc(&self) -> Arc<Slice> { + self.as_slice().into_arc() + } + + #[inline] + pub fn into_rc(&self) -> Rc<Slice> { + self.as_slice().into_rc() + } +} + +impl Slice { + fn from_u8_slice(s: &[u8]) -> &Slice { + unsafe { mem::transmute(s) } + } + + pub fn from_str(s: &str) -> &Slice { + Slice::from_u8_slice(s.as_bytes()) + } + + pub fn to_str(&self) -> Option<&str> { + str::from_utf8(&self.inner).ok() + } + + pub fn to_string_lossy(&self) -> Cow<str> { + String::from_utf8_lossy(&self.inner) + } + + pub fn to_owned(&self) -> Buf { + Buf { inner: self.inner.to_vec() } + } + + #[inline] + pub fn into_box(&self) -> Box<Slice> { + let boxed: Box<[u8]> = self.inner.into(); + unsafe { mem::transmute(boxed) } + } + + pub fn empty_box() -> Box<Slice> { + let boxed: Box<[u8]> = Default::default(); + unsafe { mem::transmute(boxed) } + } + + #[inline] + pub fn into_arc(&self) -> Arc<Slice> { + let arc: Arc<[u8]> = Arc::from(&self.inner); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) } + } + + #[inline] + pub fn into_rc(&self) -> Rc<Slice> { + let rc: Rc<[u8]> = Rc::from(&self.inner); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } + } +} diff --git a/ctr-std/src/sys/wasm/path.rs b/ctr-std/src/sys/wasm/path.rs new file mode 100644 index 0000000..395b8c1 --- /dev/null +++ b/ctr-std/src/sys/wasm/path.rs @@ -0,0 +1,29 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use path::Prefix; +use ffi::OsStr; + +#[inline] +pub fn is_sep_byte(b: u8) -> bool { + b == b'/' +} + +#[inline] +pub fn is_verbatim_sep(b: u8) -> bool { + b == b'/' +} + +pub fn parse_prefix(_: &OsStr) -> Option<Prefix> { + None +} + +pub const MAIN_SEP_STR: &'static str = "/"; +pub const MAIN_SEP: char = '/'; diff --git a/ctr-std/src/sys/wasm/pipe.rs b/ctr-std/src/sys/wasm/pipe.rs new file mode 100644 index 0000000..992e1ac --- /dev/null +++ b/ctr-std/src/sys/wasm/pipe.rs @@ -0,0 +1,35 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use sys::Void; + +pub struct AnonPipe(Void); + +impl AnonPipe { + pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn write(&self, _buf: &[u8]) -> io::Result<usize> { + match self.0 {} + } + + pub fn diverge(&self) -> ! { + match self.0 {} + } +} + +pub fn read2(p1: AnonPipe, + _v1: &mut Vec<u8>, + _p2: AnonPipe, + _v2: &mut Vec<u8>) -> io::Result<()> { + match p1.0 {} +} diff --git a/ctr-std/src/sys/wasm/process.rs b/ctr-std/src/sys/wasm/process.rs new file mode 100644 index 0000000..433e9ce --- /dev/null +++ b/ctr-std/src/sys/wasm/process.rs @@ -0,0 +1,162 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi::OsStr; +use fmt; +use io; +use sys::fs::File; +use sys::pipe::AnonPipe; +use sys::{unsupported, Void}; +use sys_common::process::{CommandEnv, DefaultEnvKey}; + +//////////////////////////////////////////////////////////////////////////////// +// Command +//////////////////////////////////////////////////////////////////////////////// + +pub struct Command { + env: CommandEnv<DefaultEnvKey> +} + +// passed back to std::process with the pipes connected to the child, if any +// were requested +pub struct StdioPipes { + pub stdin: Option<AnonPipe>, + pub stdout: Option<AnonPipe>, + pub stderr: Option<AnonPipe>, +} + +pub enum Stdio { + Inherit, + Null, + MakePipe, +} + +impl Command { + pub fn new(_program: &OsStr) -> Command { + Command { + env: Default::default() + } + } + + pub fn arg(&mut self, _arg: &OsStr) { + } + + pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> { + &mut self.env + } + + pub fn cwd(&mut self, _dir: &OsStr) { + } + + pub fn stdin(&mut self, _stdin: Stdio) { + } + + pub fn stdout(&mut self, _stdout: Stdio) { + } + + pub fn stderr(&mut self, _stderr: Stdio) { + } + + pub fn spawn(&mut self, _default: Stdio, _needs_stdin: bool) + -> io::Result<(Process, StdioPipes)> { + unsupported() + } +} + +impl From<AnonPipe> for Stdio { + fn from(pipe: AnonPipe) -> Stdio { + pipe.diverge() + } +} + +impl From<File> for Stdio { + fn from(file: File) -> Stdio { + file.diverge() + } +} + +impl fmt::Debug for Command { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +pub struct ExitStatus(Void); + +impl ExitStatus { + pub fn success(&self) -> bool { + match self.0 {} + } + + pub fn code(&self) -> Option<i32> { + match self.0 {} + } +} + +impl Clone for ExitStatus { + fn clone(&self) -> ExitStatus { + match self.0 {} + } +} + +impl Copy for ExitStatus {} + +impl PartialEq for ExitStatus { + fn eq(&self, _other: &ExitStatus) -> bool { + match self.0 {} + } +} + +impl Eq for ExitStatus { +} + +impl fmt::Debug for ExitStatus { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +impl fmt::Display for ExitStatus { + fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { + match self.0 {} + } +} + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(bool); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(false); + pub const FAILURE: ExitCode = ExitCode(true); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + +pub struct Process(Void); + +impl Process { + pub fn id(&self) -> u32 { + match self.0 {} + } + + pub fn kill(&mut self) -> io::Result<()> { + match self.0 {} + } + + pub fn wait(&mut self) -> io::Result<ExitStatus> { + match self.0 {} + } + + pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { + match self.0 {} + } +} diff --git a/ctr-std/src/sys/wasm/rwlock.rs b/ctr-std/src/sys/wasm/rwlock.rs new file mode 100644 index 0000000..6516010 --- /dev/null +++ b/ctr-std/src/sys/wasm/rwlock.rs @@ -0,0 +1,82 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cell::UnsafeCell; + +pub struct RWLock { + mode: UnsafeCell<isize>, +} + +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} // no threads on wasm + +impl RWLock { + pub const fn new() -> RWLock { + RWLock { + mode: UnsafeCell::new(0), + } + } + + #[inline] + pub unsafe fn read(&self) { + let mode = self.mode.get(); + if *mode >= 0 { + *mode += 1; + } else { + rtabort!("rwlock locked for writing"); + } + } + + #[inline] + pub unsafe fn try_read(&self) -> bool { + let mode = self.mode.get(); + if *mode >= 0 { + *mode += 1; + true + } else { + false + } + } + + #[inline] + pub unsafe fn write(&self) { + let mode = self.mode.get(); + if *mode == 0 { + *mode = -1; + } else { + rtabort!("rwlock locked for reading") + } + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + let mode = self.mode.get(); + if *mode == 0 { + *mode = -1; + true + } else { + false + } + } + + #[inline] + pub unsafe fn read_unlock(&self) { + *self.mode.get() -= 1; + } + + #[inline] + pub unsafe fn write_unlock(&self) { + *self.mode.get() += 1; + } + + #[inline] + pub unsafe fn destroy(&self) { + } +} diff --git a/ctr-std/src/sys/wasm/stack_overflow.rs b/ctr-std/src/sys/wasm/stack_overflow.rs new file mode 100644 index 0000000..bed2741 --- /dev/null +++ b/ctr-std/src/sys/wasm/stack_overflow.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct Handler; + +impl Handler { + pub unsafe fn new() -> Handler { + Handler + } +} + +pub unsafe fn init() { +} + +pub unsafe fn cleanup() { +} diff --git a/ctr-std/src/sys/wasm/stdio.rs b/ctr-std/src/sys/wasm/stdio.rs new file mode 100644 index 0000000..023f295 --- /dev/null +++ b/ctr-std/src/sys/wasm/stdio.rs @@ -0,0 +1,75 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use sys::{ReadSysCall, WriteSysCall}; + +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; + +impl Stdin { + pub fn new() -> io::Result<Stdin> { + Ok(Stdin) + } + + pub fn read(&self, data: &mut [u8]) -> io::Result<usize> { + Ok(ReadSysCall::perform(0, data)) + } +} + +impl Stdout { + pub fn new() -> io::Result<Stdout> { + Ok(Stdout) + } + + pub fn write(&self, data: &[u8]) -> io::Result<usize> { + WriteSysCall::perform(1, data); + Ok(data.len()) + } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { + pub fn new() -> io::Result<Stderr> { + Ok(Stderr) + } + + pub fn write(&self, data: &[u8]) -> io::Result<usize> { + WriteSysCall::perform(2, data); + Ok(data.len()) + } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } +} + +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + (&*self).write(data) + } + fn flush(&mut self) -> io::Result<()> { + (&*self).flush() + } +} + +pub const STDIN_BUF_SIZE: usize = 0; + +pub fn is_ebadf(_err: &io::Error) -> bool { + true +} + +pub fn stderr_prints_nothing() -> bool { + !cfg!(feature = "wasm_syscall") +} diff --git a/ctr-std/src/sys/wasm/thread.rs b/ctr-std/src/sys/wasm/thread.rs new file mode 100644 index 0000000..728e678 --- /dev/null +++ b/ctr-std/src/sys/wasm/thread.rs @@ -0,0 +1,50 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use boxed::FnBox; +use ffi::CStr; +use io; +use sys::{unsupported, Void}; +use time::Duration; + +pub struct Thread(Void); + +pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; + +impl Thread { + pub unsafe fn new<'a>(_stack: usize, _p: Box<FnBox() + 'a>) + -> io::Result<Thread> + { + unsupported() + } + + pub fn yield_now() { + // do nothing + } + + pub fn set_name(_name: &CStr) { + // nope + } + + pub fn sleep(_dur: Duration) { + panic!("can't sleep"); + } + + pub fn join(self) { + match self.0 {} + } +} + +pub mod guard { + pub type Guard = !; + pub unsafe fn current() -> Option<Guard> { None } + pub unsafe fn init() -> Option<Guard> { None } + pub unsafe fn deinit() {} +} diff --git a/ctr-std/src/sys/wasm/thread_local.rs b/ctr-std/src/sys/wasm/thread_local.rs new file mode 100644 index 0000000..442dd33 --- /dev/null +++ b/ctr-std/src/sys/wasm/thread_local.rs @@ -0,0 +1,50 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use boxed::Box; +use ptr; + +pub type Key = usize; + +struct Allocated { + value: *mut u8, + dtor: Option<unsafe extern fn(*mut u8)>, +} + +#[inline] +pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key { + Box::into_raw(Box::new(Allocated { + value: ptr::null_mut(), + dtor, + })) as usize +} + +#[inline] +pub unsafe fn set(key: Key, value: *mut u8) { + (*(key as *mut Allocated)).value = value; +} + +#[inline] +pub unsafe fn get(key: Key) -> *mut u8 { + (*(key as *mut Allocated)).value +} + +#[inline] +pub unsafe fn destroy(key: Key) { + let key = Box::from_raw(key as *mut Allocated); + if let Some(f) = key.dtor { + f(key.value); + } +} + +#[inline] +pub fn requires_synchronized_create() -> bool { + false +} diff --git a/ctr-std/src/sys/wasm/time.rs b/ctr-std/src/sys/wasm/time.rs new file mode 100644 index 0000000..e52435e --- /dev/null +++ b/ctr-std/src/sys/wasm/time.rs @@ -0,0 +1,57 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use time::Duration; +use sys::{TimeSysCall, TimeClock}; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(Duration); + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(Duration); + +pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); + +impl Instant { + pub fn now() -> Instant { + Instant(TimeSysCall::perform(TimeClock::Monotonic)) + } + + pub fn sub_instant(&self, other: &Instant) -> Duration { + self.0 - other.0 + } + + pub fn add_duration(&self, other: &Duration) -> Instant { + Instant(self.0 + *other) + } + + pub fn sub_duration(&self, other: &Duration) -> Instant { + Instant(self.0 - *other) + } +} + +impl SystemTime { + pub fn now() -> SystemTime { + SystemTime(TimeSysCall::perform(TimeClock::System)) + } + + pub fn sub_time(&self, other: &SystemTime) + -> Result<Duration, Duration> { + self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + } + + pub fn add_duration(&self, other: &Duration) -> SystemTime { + SystemTime(self.0 + *other) + } + + pub fn sub_duration(&self, other: &Duration) -> SystemTime { + SystemTime(self.0 - *other) + } +} |