Initial commit

legacy
Avril 4 years ago
commit 38dd291c43
Signed by: flanchan
GPG Key ID: 284488987C31F630

2
.gitignore vendored

@ -0,0 +1,2 @@
/target
*~

603
Cargo.lock generated

@ -0,0 +1,603 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "arc-swap"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
[[package]]
name = "async-trait"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "687c230d85c0a52504709705fc8a53e4a692b83a2184f03dae73e38e1e93a783"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
]
[[package]]
name = "bytes"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "chrono"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
dependencies = [
"num-integer",
"num-traits",
"time",
]
[[package]]
name = "cpuid-bool"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
[[package]]
name = "cryptohelpers"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8689d930e1c3d1cbd99014c9f7bf1a1197db8e0665ff134517b86c78233ef4fb"
dependencies = [
"libc",
"sha2",
"tokio",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
"bitflags",
"fuchsia-zircon-sys",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "futures-core"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
[[package]]
name = "generic-array"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
dependencies = [
"cfg-if",
"libc",
"wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
name = "hermit-abi"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
dependencies = [
"libc",
]
[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
dependencies = [
"libc",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "mio"
version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
dependencies = [
"cfg-if",
"fuchsia-zircon",
"fuchsia-zircon-sys",
"iovec",
"kernel32-sys",
"libc",
"log",
"miow 0.2.1",
"net2",
"slab",
"winapi 0.2.8",
]
[[package]]
name = "mio-named-pipes"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
dependencies = [
"log",
"mio",
"miow 0.3.5",
"winapi 0.3.9",
]
[[package]]
name = "mio-uds"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
dependencies = [
"iovec",
"libc",
"mio",
]
[[package]]
name = "miow"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
dependencies = [
"kernel32-sys",
"net2",
"winapi 0.2.8",
"ws2_32-sys",
]
[[package]]
name = "miow"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"
dependencies = [
"socket2",
"winapi 0.3.9",
]
[[package]]
name = "net2"
version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
dependencies = [
"cfg-if",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "num-integer"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "pin-project-lite"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
[[package]]
name = "ppv-lite86"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
[[package]]
name = "proc-macro2"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "sha2"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1"
dependencies = [
"block-buffer",
"cfg-if",
"cpuid-bool",
"digest",
"opaque-debug",
]
[[package]]
name = "signal-hook-registry"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035"
dependencies = [
"arc-swap",
"libc",
]
[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "socket2"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"winapi 0.3.9",
]
[[package]]
name = "syn"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi 0.3.9",
]
[[package]]
name = "tokio"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
dependencies = [
"bytes",
"fnv",
"futures-core",
"iovec",
"lazy_static",
"libc",
"memchr",
"mio",
"mio-named-pipes",
"mio-uds",
"num_cpus",
"pin-project-lite",
"signal-hook-registry",
"slab",
"tokio-macros",
"winapi 0.3.9",
]
[[package]]
name = "tokio-macros"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "uuid"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
dependencies = [
"rand",
]
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "yuurei"
version = "0.1.0"
dependencies = [
"async-trait",
"chrono",
"cryptohelpers",
"once_cell",
"rustc_version",
"tokio",
"uuid",
]

@ -0,0 +1,18 @@
[package]
name = "yuurei"
version = "0.1.0"
authors = ["Avril <flanchan@cumallover.me>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = {version = "0.2", features=["full"]}
async-trait = "0.1.40"
chrono = "0.4.15"
uuid = {version = "0.8", features=["v4"]}
once_cell = "1.4.1"
crypto = {package= "cryptohelpers", version = "0.1", features= ["async", "sha256"]}
[build-dependencies]
rustc_version = "0.2"

@ -0,0 +1,24 @@
extern crate rustc_version;
use rustc_version::{version, version_meta, Channel};
fn main() {
// Assert we haven't travelled back in time
assert!(version().unwrap().major >= 1);
// Set cfg flags depending on release channel
match version_meta().unwrap().channel {
Channel::Stable => {
println!("cargo:rustc-cfg=stable");
}
Channel::Beta => {
println!("cargo:rustc-cfg=beta");
}
Channel::Nightly => {
println!("cargo:rustc-cfg=nightly");
}
Channel::Dev => {
println!("cargo:rustc-cfg=dev");
}
}
}

@ -0,0 +1,26 @@
pub unsafe fn refer<'a, T>(src: &'a T) -> &'a [u8]
where T: ?Sized
{
std::slice::from_raw_parts(src as *const T as *const u8, std::mem::size_of_val(src))
}
pub unsafe fn refer_mut<'a, T>(src: &'a mut T) -> &'a mut [u8]
where T: ?Sized
{
std::slice::from_raw_parts_mut(src as *mut T as *mut u8, std::mem::size_of_val(src))
}
pub unsafe fn derefer<'a, T>(src: &'a [u8]) -> &'a T
{
assert!(src.len() >= std::mem::size_of::<T>());
&*(&src[0] as *const u8 as *const T)
}
pub unsafe fn derefer_mut<'a, T>(src: &'a mut [u8]) -> &'a mut T
{
assert!(src.len() >= std::mem::size_of::<T>());
&mut *(&mut src[0] as *mut u8 as *mut T)
}

@ -0,0 +1,40 @@
use super::*;
//TODO: Use tokio Watcher instead, to allow hotreloading?
use once_cell::sync::OnceCell;
static INSTANCE: OnceCell<Config> = OnceCell::new();
/// Set the global config instance.
/// This can only be done once for the duration of the program's runtime
pub fn set(conf: Config)
{
INSTANCE.set(conf).expect("Failed to set global config state: Already set");
}
/// Get the global config instance.
/// `set()` must have been previously called or this function panics.
pub fn get() -> &'static Config
{
INSTANCE.get().expect("Global config tried to be accessed before it was set")
}
/// Config for this run
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Config
{
/// Name for nanashi
pub anon_name: String,
}
impl Default for Config
{
#[inline]
fn default() -> Self
{
Self {
anon_name: "Nanashi",
}
}
}

@ -0,0 +1,64 @@
//! Handles post and user identity.
use super::*;
use std::{
fmt,
};
use uuid::Uuid;
/// A globally unique post identifier.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct PostID(Uuid);
impl PostID
{
/// Generate a new `PostID`.
pub fn new() -> Self
{
Self(Uuid::new_v4())
}
}
impl fmt::Display for PostID
{
#[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
self.0.fmt(f) //TODO: Change to use kana-hash.
}
}
/// A user's data, if set.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct User
{
pub name: Option<String>,
pub email: Option<String>,
pub tripcode: Option<tripcode::Tripcode>,
}
impl User
{
/// The name string of this instance, or the default name.
pub fn name_str(&self) -> &str
{
self.name.as_ref().map(|x| &x[..]).unwrap_or(&config::get().anon_name[..])
}
/// The email string of this instance, if it is set
pub fn email_str(&self) -> Option<&str>
{
self.email.as_ref().map(|x| &x[..])
}
// No str for tripcode because it's not just a string (yet)
/// Anon with no detials.
pub const fn anon() -> Self
{
Self {
name: None,
email: None,
tripcode: None,
}
}
}

@ -0,0 +1,19 @@
#![cfg_attr(nightly, feature(option_unwrap_none))]
#![cfg_attr(nightly, feature(never_type))]
#![allow(dead_code)]
use async_trait::async_trait;
mod bytes;
mod suspend;
mod config;
mod tripcode;
mod identity;
mod post;
mod state;
fn main() {
println!("Hello, world!");
}

@ -0,0 +1,64 @@
//! Structure for updating posts in-place
use super::*;
use std::{
fmt,
hash::{
Hash,Hasher,
},
};
use chrono::prelude::*;
/// Represents all valid timestamps for a post.
///
/// Usually in UTC, pls keep it in Utc...
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PostTimestamp<T = Utc>
where T: TimeZone,
{
pub opened: DateTime<T>,
pub closed: Option<DateTime<T>>,
pub last_edit: DateTime<T>,
}
impl<Tz: TimeZone> Hash for PostTimestamp<Tz> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.opened.hash(state);
self.closed.hash(state);
self.last_edit.hash(state);
}
}
impl<T> fmt::Display for PostTimestamp<T>
where T: TimeZone,
T::Offset: fmt::Display
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
writeln!(f, " Opened - {}", self.opened)?;
writeln!(f, " Edited - {}", self.last_edit)?;
write!(f, " Closed - ")?;
if let Some(closed) = &self.closed {
writeln!(f, "{}", closed)?;
} else {
writeln!(f, "Stil open")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// A closed and finished post. The inverse of `Imouto`.
pub struct Static
{
id: identity::PostID,
user: identity::User,
title: Option<String>,
karada: String,
timestamp: PostTimestamp,
/// Hash of the rest of the post data. . . .
hash: crypto::sha256::Sha256Hash,
}

@ -0,0 +1,8 @@
//! Container state for all posts
use super::*;
/// Contains all posts in an instance, open or closed.
pub struct Oneesan
{
}

@ -0,0 +1,91 @@
//! Handles updating posts
use super::*;
use tokio::{
sync::{
RwLock,
watch,
},
};
const MAX_SINGLE_DELTA_SIZE: usize = 16;
/// Information about the delta to be applied in `Delta`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DeltaKind
{
/// Append to the end of body. Equivilant to `Insert` with a location at `karada.scape.len()` (the end of the buffer). Might be removed idk
Append{
span: [char; MAX_SINGLE_DELTA_SIZE],
span_len: u8,
},
/// Insert `span_len` chars from `span` into body starting ahead of `location` and moving ahead
Insert{
span: [char; MAX_SINGLE_DELTA_SIZE],
span_len: u8,
},
/// Remove `span_len` chars ahead of `location`. (INCLUSIVE)
RemoveAhead{
span_len: usize,
},
/// Remove `span_len` chars behind this `location`. (EXCLUSIVE)
RemoveBehind{
span_len: usize,
},
/// Remove char at `location`
RemoveSingle,
/// Remove entire post body
Clear,
}
/// A delta to apply to `Karada`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Delta
{
/// Location to insert into. This is the INclusive range of: 0..=(karada.scape.len()).
///
/// Insertions off the end of the buffer are to be appened instead.
location: usize,
/// The kind of delta t oinsert
kind: DeltaKind,
}
/// Static assertion: `MAX_SINGLE_DELTA_SIZE` can fit into `u8`.
const _: [u8;(MAX_SINGLE_DELTA_SIZE < (!0u8 as usize)) as usize] = [0];
/// Contains post deltas and an intermediate representation of the still-open post body.
/// Created and modified with `Kokoro` worker instances.
///
/// This should not be created by itself, instead `Kokoro` should create instances of this, so that it can retain the `watch::Sender` and other such things.
#[derive(Debug)]
pub struct Karada
{
/// The post body so far as a vector of `char`s.
scape: RwLock<Vec<char>>,
/// All applied deltas so far. Last applied one is at the end.
deltas: RwLock<Vec<Delta>>,
/// the latest render of the whole body string. Updated whenever a delta(s) are applied atomically.
current_body: watch::Receiver<String>,
}
/// Handles working on `Karada` instances.
pub struct Kokoro
{
...//TODO
}
/// An open, as yet unfinied post
#[derive(Debug)]
pub struct Imouto
{
id: identity::PostID,
user: identity::User,
title: Option<String>,
karada: Karada,
/// Hash of the current post data
hash: crypto::sha256::Sha256Hash,
timestamp: post::PostTimestamp, //Note that `closed` should always be `None` in `Imouto`. We use this for post lifetimes and such
}

@ -0,0 +1,15 @@
//! Structures for handling global and local post state.
use super::*;
mod global;
pub use global::*;
mod local;
pub use local::*;
/// An open or closed post
pub enum Post
{
Open(Imouto),
Closed(post::Static),
}

@ -0,0 +1,304 @@
//! Handles suspending and reloading posts
use super::*;
use std::{
marker::{
PhantomData,
Unpin,
},
io,
collections::HashMap,
ops::Range,
borrow::{
Cow,
Borrow,
},
error,
fmt,
};
use tokio::{
prelude::*,
io::{
AsyncRead,
AsyncWrite,
},
};
/// Represents an opaque bytes stream of serialised data to insert into `SuspendStream`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SuspendObject
{
data: Vec<u8>,
data_instances: HashMap<Cow<'static, str>, Range<usize>>,
}
fn calc_len<T,I,U>(from: I) -> U
where I: IntoIterator<Item = T>,
T: Borrow<Range<U>>,
U: std::cmp::Ord + Default + Copy,
{
let mut max = Default::default();
for i in from.into_iter()
{
let i = i.borrow().end;
if i > max {
max = i
}
}
max
}
impl SuspendObject
{
/// Create a new empty `SuspendObject`.
#[inline] pub fn new() -> Self
{
Self{data: Vec::new(), data_instances: HashMap::new()}
}
/// Are the internal mappings of this object valid?
pub fn validate(&self) -> bool
{
let len = self.data.len();
for (_, range) in self.data_instances.iter() {
if range.start + range.end > len {
return false;
}
}
true
}
/// Insert bytes directly with this name
pub fn insert_bytes(&mut self, name: impl Into<Cow<'static, str>>, bytes: impl AsRef<[u8]>)
{
let bytes= bytes.as_ref();
let start = self.data.len();
self.data.extend_from_slice(bytes);
let end = self.data.len();
self.data_instances.insert(name.into(), start..end).unwrap_none();
}
/// Insert a value's bytes directly with this name
pub unsafe fn insert_value<T,U>(&mut self, name: U, value: &T)
where T: ?Sized,
U: Into<Cow<'static, str>>
{
self.insert_bytes(name, bytes::refer(value))
}
/// Try to get the bytes specified by name
pub fn get_bytes(&self, name: impl Borrow<str>) -> Option<&[u8]>
{
if let Some(range) = self.data_instances.get(name.borrow()) {
Some(&self.data[range.clone()])
} else {
None
}
}
/// Try to get the value spcified by name
///
/// # Panics
/// If `T` cannot fit into the size of the range
pub unsafe fn get_value<T>(&self, name: impl Borrow<str>) -> Option<&T>
{
self.get_bytes(name).map(|x| bytes::derefer(x))
}
/// Try to get the value specified by name. Will return `None` if `T` cannot fit in the returned bytes.
pub unsafe fn try_get_value<T>(&self, name: impl Borrow<str>) -> Option<&T>
{
if let Some(bytes) = self.get_bytes(name) {
if bytes.len() >= std::mem::size_of::<T>() {
Some(bytes::derefer(bytes))
} else {
#[cfg(debug_assertions)] eprintln!("Warning! Likely data corruption as {} (size {}) cannot fit into {} bytes",std::any::type_name::<T>(), std::mem::size_of::<T>(), bytes.len());
None
}
} else {
None
}
}
/// Consume into the data
#[deprecated = "Invalid ABI"] fn into_bytes(self) -> Box<[u8]>
{
let mut output = Vec::new(); //TOOO: Get cap
debug_assert!(self.validate(), "passing invalid object to serialise");
unsafe {
output.extend_from_slice(bytes::refer(&self.data_instances.len()));
for (name, Range{start, end}) in self.data_instances.into_iter() {
let name = name.as_bytes();
output.extend_from_slice(bytes::refer(&name.len()));
output.extend_from_slice(name);
output.extend_from_slice(bytes::refer(&start));
output.extend_from_slice(bytes::refer(&end));
}
}
output.extend(self.data);
output.into_boxed_slice()
}
/// Read an object from a stream
pub async fn from_stream<T>(input: &mut T) -> io::Result<Self>
where T: AsyncRead + Unpin + ?Sized
{
let mut ext_buf = Vec::new();
macro_rules! bin {
(usize) => {
{
use std::convert::TryFrom;
let value: u64 = input.read_u64().await?;
usize::try_from(value).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "u64 cannot fit in usize"))?
}
};
($size:expr) => {
{
let sz = $size;
ext_buf.resize(sz, 0);
assert_eq!(input.read_exact(&mut ext_buf[..sz]).await?, ext_buf.len());
&ext_buf[..sz]
}
}
}
let entries = bin!(usize);
let mut instances = HashMap::with_capacity(entries);
for _i in 0..entries
{
let name_len = bin!(usize);
let name_bytes = bin!(name_len);
let name_str = std::str::from_utf8(name_bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData,"item name was corrupted"))?;
let start = bin!(usize);
let end = bin!(usize);
instances.insert(Cow::Owned(name_str.to_owned()), start..end);
}
let expected_len = bin!(usize);
if expected_len != calc_len(instances.iter().map(|(_, v)| v))
{
return Err(io::Error::new(io::ErrorKind::InvalidData, "expected and read sizes differ"));
}
let mut data = vec![0; expected_len];
assert_eq!(input.read_exact(&mut data[..]).await?, expected_len);
Ok(Self {
data,
data_instances: instances,
})
}
/// Write this instance into an async stream
pub async fn into_stream<T>(&self, output: &mut T) -> io::Result<usize>
where T: AsyncWrite + Unpin + ?Sized
{
debug_assert!(self.validate(), "passing invalid object to serialise");
let mut written=0usize;
macro_rules! bin {
($bytes:expr) => {
{
let bytes = $bytes;
output.write_all(bytes).await?;
written+=bytes.len();
}
};
(usize $value:expr) => {
{
use std::convert::TryInto;
let val: u64 = $value.try_into().map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "size cannot fit in u64"))?;
output.write_u64(val).await?;
written += std::mem::size_of::<u64>();
}
};
}
unsafe {
bin!(usize self.data_instances.len());
for (name, &Range{start, end}) in self.data_instances.iter() {
let name = name.as_bytes();
bin!(usize name.len());
bin!(name);
bin!(usize start);
bin!(usize end);
}
}
bin!(usize self.data.len()); //for additional checks
bin!(&self.data);
Ok(written)
}
}
/// A suspend stream represents a stream of objects of _the same type_. Can be any number of them, but they all must be for the same type.
#[async_trait]
pub trait SuspendStream
{
/// Write an object into the opaque stream.
async fn set_object(&mut self, obj: SuspendObject) -> Result<(), SuspendError>;
/// Read an object from the opaque stream.
async fn get_object(&mut self) -> Result<Option<SuspendObject>, SuspendError>;
}
/// An error that occoured in a suspend operation
#[derive(Debug)]
#[non_exhaustive]
pub enum SuspendError {
BadObject,
Corruption,
IO(io::Error),
Unknown,
}
impl error::Error for SuspendError
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(match &self {
Self::IO(io) => io,
_ => return None,
})
}
}
impl fmt::Display for SuspendError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::BadObject => write!(f, "unexpected object in stream"),
Self::Corruption => write!(f, "data stream corruption"),
Self::IO(_) => write!(f, "i/o error"),
_ => write!(f, "unknown error"),
}
}
}
/// A suspendable type, that can save and reload its data atomically
#[async_trait]
pub trait Suspendable: Sized
{
async fn suspend<S: SuspendStream + ?Sized>(self, into: &mut S) -> Result<(), SuspendError>;
async fn load<S: SuspendStream + ?Sized>(from: &mut S) -> Result<Self, SuspendError>;
}
/*
pub struct SuspenceState<T>
where T: Suspendable
{
_phantom: PhantomData<T>,
}*/

@ -0,0 +1,12 @@
//! Tripcode. TODO: Use kana-hash
use super::*;
///TODO: A kana-hash tripcode
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum Tripcode
{
Secure(i32),
Normal(i32),
Special(&'static str),
}
Loading…
Cancel
Save