initial import of main veilid core

This commit is contained in:
John Smith
2021-11-22 11:28:30 -05:00
parent c4cd54e020
commit 9e94a6a96f
218 changed files with 34880 additions and 1 deletions

View File

@@ -0,0 +1,140 @@
use crate::xx::*;
use alloc::collections::VecDeque;
#[derive(Debug)]
pub struct Channel<T> {
items: VecDeque<T>,
cap: usize,
eventual: Eventual,
}
#[derive(Debug)]
pub struct Sender<T> {
imp: Arc<Mutex<Channel<T>>>,
}
impl<T> Clone for Sender<T> {
fn clone(&self) -> Self {
Self {
imp: self.imp.clone(),
}
}
}
#[derive(Debug)]
pub struct Receiver<T> {
imp: Arc<Mutex<Channel<T>>>,
}
impl<T> Clone for Receiver<T> {
fn clone(&self) -> Self {
Self {
imp: self.imp.clone(),
}
}
}
pub fn channel<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
let imp = Channel {
items: VecDeque::with_capacity(cap),
cap: cap,
eventual: Eventual::new(),
};
let imparc = Arc::new(Mutex::new(imp));
(
Sender {
imp: imparc.clone(),
},
Receiver {
imp: imparc.clone(),
},
)
}
#[derive(Debug, PartialEq, Eq)]
pub enum TrySendError<T> {
Full(T),
Disconnected(T),
}
impl<T> Sender<T> {
// NOTE: This needs a timeout or you could block a very long time
// pub async fn send(&self, msg: T) -> Result<(), SendError<T>> {
// xxx
// }
pub async fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
let eventual = {
let mut inner = self.imp.lock();
if inner.items.len() == inner.cap {
return Err(TrySendError::Full(msg));
}
let empty = inner.items.is_empty();
inner.items.push_back(msg);
if empty {
Some(inner.eventual.clone())
} else {
None
}
};
if let Some(e) = eventual {
e.resolve().await;
}
Ok(())
}
pub fn capacity(&self) -> usize {
self.imp.lock().cap
}
pub fn is_empty(&self) -> bool {
self.imp.lock().items.is_empty()
}
pub fn is_full(&self) -> bool {
let inner = self.imp.lock();
inner.items.len() == inner.cap
}
pub fn len(&self) -> usize {
self.imp.lock().items.len()
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct RecvError;
#[derive(Debug, PartialEq, Eq)]
pub enum TryRecvError {
Empty,
Disconnected,
}
impl<T> Receiver<T> {
pub async fn recv(&self) -> Result<T, RecvError> {
let eventual = {
let inner = self.imp.lock();
inner.eventual.clone()
};
while self.is_empty() {
eventual.instance_clone(true).await;
}
Ok(self.imp.lock().items.pop_front().unwrap())
}
pub async fn try_recv(&self) -> Result<T, TryRecvError> {
if self.is_empty() {
return Err(TryRecvError::Empty);
}
Ok(self.imp.lock().items.pop_front().unwrap())
}
pub fn capacity(&self) -> usize {
self.imp.lock().cap
}
pub fn is_empty(&self) -> bool {
self.imp.lock().items.is_empty()
}
pub fn is_full(&self) -> bool {
let inner = self.imp.lock();
inner.items.len() == inner.cap
}
pub fn len(&self) -> usize {
self.imp.lock().items.len()
}
}

View File

@@ -0,0 +1,91 @@
#![cfg(target_arch = "wasm32")]
pub mod channel;
use crate::xx::*;
use core::sync::atomic::{AtomicI8, Ordering};
use js_sys::{global, Reflect};
cfg_if! {
if #[cfg(feature = "wee_alloc")] {
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
}
}
#[wasm_bindgen]
extern "C" {
// Use `js_namespace` here to bind `console.log(..)` instead of just
// `log(..)`
#[wasm_bindgen(js_namespace = console, js_name = log)]
pub fn console_log(s: &str);
#[wasm_bindgen]
pub fn alert(s: &str);
}
pub fn is_nodejs() -> bool {
static CACHE: AtomicI8 = AtomicI8::new(-1);
let cache = CACHE.load(Ordering::Relaxed);
if cache != -1 {
return cache != 0;
}
let res = js_sys::eval("process.release.name === 'node'")
.map(|res| res.is_truthy())
.unwrap_or_default();
CACHE.store(res as i8, Ordering::Relaxed);
res
}
pub fn is_browser() -> bool {
static CACHE: AtomicI8 = AtomicI8::new(-1);
let cache = CACHE.load(Ordering::Relaxed);
if cache != -1 {
return cache != 0;
}
let res = Reflect::has(&global().as_ref(), &"window".into()).unwrap_or_default();
CACHE.store(res as i8, Ordering::Relaxed);
res
}
pub fn is_browser_https() -> bool {
static CACHE: AtomicI8 = AtomicI8::new(-1);
let cache = CACHE.load(Ordering::Relaxed);
if cache != -1 {
return cache != 0;
}
let res = js_sys::eval("window.location.protocol === 'https'")
.map(|res| res.is_truthy())
.unwrap_or_default();
CACHE.store(res as i8, Ordering::Relaxed);
res
}
pub fn node_require(module: &str) -> JsValue {
if !is_nodejs() {
return JsValue::UNDEFINED;
}
let mut home = env!("CARGO_MANIFEST_DIR");
if home.len() == 0 {
home = ".";
}
match js_sys::eval(format!("require(\"{}/{}\")", home, module).as_str()) {
Ok(v) => v,
Err(e) => {
panic!("node_require failed: {:?}", e);
}
}
}