/* * Copyright (C) 2023 - 2024: * The Trinitrix Project * * This file is part of the Trixy crate for Trinitrix. * * Trixy is free software: you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * and the Lesser GNU General Public License along with this program. * If not, see . */ pub mod types { pub use trixy_types::*; } pub mod macros { pub use trixy_macros::*; } pub mod oneshot { //! This module provides a synced version of tokio's oneshot channel. //! Notably this is implemented as wrapper around std's mpsc channel, which closes after one received value use std::{ mem, sync::mpsc::{self, RecvError, SendError, TryRecvError}, }; #[derive(Clone, Debug)] pub struct Sender { channel: mpsc::Sender, } #[derive(Debug)] pub struct Receiver { channel: mpsc::Receiver, last_value: Option, } pub fn channel() -> (Sender, Receiver) { let (tx, rx) = mpsc::channel(); ( Sender { channel: tx }, Receiver { channel: rx, last_value: None, }, ) } impl Sender { pub fn send(&self, input: T) -> Result<(), SendError> { self.channel.send(input) } } impl Receiver { pub fn try_recv(&mut self) -> Result { match self.channel.try_recv() { Ok(ok) => { self.close(); self.last_value = Some(ok); Ok(true) } Err(err) => Err(err), } } pub fn close(&mut self) { let (_, recv) = mpsc::channel(); let channel = mem::replace(&mut self.channel, recv); drop(channel); } pub fn recv(mut self) -> Result { match self.channel.recv() { Ok(ok) => { self.close(); Ok(ok) } Err(err) => { if let Some(val) = self.last_value { Ok(val) } else { Err(err) } } } } } }