init
This commit is contained in:
18
.idea/dataSources.local.xml
generated
Normal file
18
.idea/dataSources.local.xml
generated
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="dataSourceStorageLocal" created-in="RR-251.26927.79">
|
||||
<data-source name="db.sqlite" uuid="26059583-0fdb-4f6f-ad11-10388e9658c2">
|
||||
<database-info product="SQLite" version="3.45.1" jdbc-version="4.2" driver-name="SQLite JDBC" driver-version="3.45.1.0" dbms="SQLITE" exact-version="3.45.1" exact-driver-version="3.45">
|
||||
<identifier-quote-string>"</identifier-quote-string>
|
||||
</database-info>
|
||||
<case-sensitivity plain-identifiers="mixed" quoted-identifiers="mixed" />
|
||||
<secret-storage>master_key</secret-storage>
|
||||
<auth-provider>no-auth</auth-provider>
|
||||
<schema-mapping>
|
||||
<introspection-scope>
|
||||
<node kind="schema" qname="@" />
|
||||
</introspection-scope>
|
||||
</schema-mapping>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/dataSources.xml
generated
Normal file
12
.idea/dataSources.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="db.sqlite" uuid="26059583-0fdb-4f6f-ad11-10388e9658c2">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db.sqlite</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
1923
.idea/dataSources/26059583-0fdb-4f6f-ad11-10388e9658c2.xml
generated
Normal file
1923
.idea/dataSources/26059583-0fdb-4f6f-ad11-10388e9658c2.xml
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
.idea/dataSources/26059583-0fdb-4f6f-ad11-10388e9658c2/storage_v2/_src_/schema/main.uQUzAA.meta
generated
Normal file
2
.idea/dataSources/26059583-0fdb-4f6f-ad11-10388e9658c2/storage_v2/_src_/schema/main.uQUzAA.meta
generated
Normal file
@@ -0,0 +1,2 @@
|
||||
#n:main
|
||||
!<md> [0, 0, null, null, -2147483648, -2147483648]
|
||||
37
.idea/workspace.xml
generated
37
.idea/workspace.xml
generated
@@ -15,7 +15,18 @@
|
||||
</cargoProject>
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="ca698286-778f-4335-97c8-da35a666c986" name="Changes" comment="init" />
|
||||
<list default="true" id="ca698286-778f-4335-97c8-da35a666c986" name="Changes" comment="init">
|
||||
<change afterPath="$PROJECT_DIR$/src/network/http_routes/sub_server.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/network/http_routes/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/network/http_routes/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/channel_repository.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/store/repositories/channel_repository.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/link_sub_server_user_repository.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/store/repositories/link_sub_server_user_repository.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/message_repository.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/store/repositories/message_repository.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/sub_server_repository.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/store/repositories/sub_server_repository.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/repositories/user_repository.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/store/repositories/user_repository.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/store/store_service.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/store/store_service.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/utils/shared_store.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/shared_store.rs" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
@@ -68,8 +79,13 @@
|
||||
"org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "",
|
||||
"org.rust.first.attach.projects": "true",
|
||||
"run.code.analysis.last.selected.profile": "pProject Default",
|
||||
"settings.editor.selected.configurable": "terminal",
|
||||
"settings.editor.selected.configurable": "ml.llm.LLMProjectConfigurable",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
},
|
||||
"keyToStringList": {
|
||||
"DatabaseDriversLRU": [
|
||||
"sqlite"
|
||||
]
|
||||
}
|
||||
}</component>
|
||||
<component name="RecentsManager">
|
||||
@@ -141,6 +157,19 @@
|
||||
<workItem from="1753804642657" duration="236000" />
|
||||
<workItem from="1753804898179" duration="625000" />
|
||||
<workItem from="1753805533139" duration="2956000" />
|
||||
<workItem from="1753868593668" duration="550000" />
|
||||
<workItem from="1753869165302" duration="389000" />
|
||||
<workItem from="1753869606067" duration="448000" />
|
||||
<workItem from="1753870068458" duration="3339000" />
|
||||
<workItem from="1753975758350" duration="2576000" />
|
||||
<workItem from="1754003476744" duration="2622000" />
|
||||
<workItem from="1754006134163" duration="1746000" />
|
||||
<workItem from="1754007911864" duration="414000" />
|
||||
<workItem from="1754039613630" duration="3435000" />
|
||||
<workItem from="1754131509073" duration="779000" />
|
||||
<workItem from="1754132326149" duration="52000" />
|
||||
<workItem from="1754132390785" duration="5048000" />
|
||||
<workItem from="1754211612647" duration="2131000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="init">
|
||||
<option name="closed" value="true" />
|
||||
@@ -199,4 +228,8 @@
|
||||
<MESSAGE value="init" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="init" />
|
||||
</component>
|
||||
<component name="XSLT-Support.FileAssociations.UIState">
|
||||
<expand />
|
||||
<select />
|
||||
</component>
|
||||
</project>
|
||||
@@ -2,4 +2,5 @@ pub mod user;
|
||||
pub mod channel;
|
||||
pub mod message;
|
||||
pub mod websocket;
|
||||
pub mod master;
|
||||
pub mod master;
|
||||
mod sub_server;
|
||||
0
src/network/http_routes/sub_server.rs
Normal file
0
src/network/http_routes/sub_server.rs
Normal file
@@ -2,6 +2,7 @@ use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
use uuid::Uuid;
|
||||
use crate::store::models::channel::Channel;
|
||||
use crate::store::models::Message;
|
||||
use crate::store::store_service::StoreService;
|
||||
use crate::utils::shared_store::SharedArcMap;
|
||||
|
||||
@@ -71,7 +72,7 @@ impl ChannelRepository {
|
||||
}
|
||||
|
||||
pub async fn delete(&self, id: Uuid) -> Result<bool, sqlx::Error> {
|
||||
let rows_affected = sqlx::query("DELETE FROM sub_server WHERE id = ?")
|
||||
let rows_affected = sqlx::query("DELETE FROM channel WHERE id = ?")
|
||||
.bind(&id)
|
||||
.execute(&self.store.db)
|
||||
.await?
|
||||
@@ -84,17 +85,13 @@ impl ChannelRepository {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pour initialiser le cache depuis la DB
|
||||
pub async fn load_all_from_db(&self) -> Result<(), sqlx::Error> {
|
||||
let servers: Vec<Channel> = sqlx::query_as("SELECT * FROM sub_server")
|
||||
impl ChannelRepository {
|
||||
// getters (db)
|
||||
pub async fn db_all(&self) -> Result<Vec<Channel>, sqlx::Error> {
|
||||
sqlx::query_as("SELECT * FROM channel")
|
||||
.fetch_all(&self.store.db)
|
||||
.await?;
|
||||
|
||||
for server in servers {
|
||||
self.store.channels.insert(server.id, server);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -63,5 +63,13 @@ impl LinkSubServerUserRepository {
|
||||
|
||||
Ok(through)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl LinkSubServerUserRepository {
|
||||
// getters (db)
|
||||
pub async fn db_all(&self) -> Result<Vec<LinkSubServerUser>, sqlx::Error> {
|
||||
sqlx::query_as("SELECT * FROM sub_server_users")
|
||||
.fetch_all(&self.store.db)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ impl MessageRepository {
|
||||
}
|
||||
|
||||
impl MessageRepository {
|
||||
// getters
|
||||
|
||||
// getters (caches)
|
||||
}
|
||||
|
||||
impl MessageRepository {
|
||||
@@ -50,7 +49,6 @@ impl MessageRepository {
|
||||
.bind(&message.id)
|
||||
.execute(&self.store.db)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -67,4 +65,13 @@ impl MessageRepository {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MessageRepository {
|
||||
// getters (db)
|
||||
pub async fn db_all(&self) -> Result<Vec<Message>, sqlx::Error> {
|
||||
sqlx::query_as("SELECT * FROM message")
|
||||
.fetch_all(&self.store.db)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
use uuid::Uuid;
|
||||
use crate::store::models::Channel;
|
||||
use crate::store::models::sub_server::SubServer;
|
||||
use crate::store::store_service::StoreService;
|
||||
use crate::utils::shared_store::SharedArcMap;
|
||||
@@ -79,17 +80,13 @@ impl SubServerRepository {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pour initialiser le cache depuis la DB
|
||||
pub async fn load_all_from_db(&self) -> Result<(), sqlx::Error> {
|
||||
let servers: Vec<SubServer> = sqlx::query_as("SELECT * FROM sub_server")
|
||||
impl SubServerRepository {
|
||||
// getters (db)
|
||||
pub async fn db_all(&self) -> Result<Vec<SubServer>, sqlx::Error> {
|
||||
sqlx::query_as("SELECT * FROM sub_server")
|
||||
.fetch_all(&self.store.db)
|
||||
.await?;
|
||||
|
||||
for server in servers {
|
||||
self.store.sub_servers.insert(server.id, server);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,18 @@ use std::sync::Arc;
|
||||
use sqlx::SqlitePool;
|
||||
use uuid::Uuid;
|
||||
use crate::store::models::user::User;
|
||||
use crate::store::store_service::StoreService;
|
||||
use crate::utils::shared_store::SharedArcMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct UserRepository {
|
||||
db: SqlitePool,
|
||||
cache: SharedArcMap<Uuid, User>
|
||||
store: StoreService,
|
||||
}
|
||||
|
||||
impl UserRepository {
|
||||
pub fn new(db: SqlitePool, cache: SharedArcMap<Uuid, User>) -> Self {
|
||||
pub fn new(store: StoreService) -> Self {
|
||||
Self {
|
||||
db,
|
||||
cache
|
||||
store
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,11 +21,11 @@ impl UserRepository {
|
||||
impl UserRepository {
|
||||
// getters
|
||||
pub async fn all(&self) -> Vec<Arc<User>> {
|
||||
self.cache.values().collect()
|
||||
self.store.users.values().collect()
|
||||
}
|
||||
|
||||
pub async fn get(&self, id: Uuid) -> Option<Arc<User>> {
|
||||
self.cache.get(&id)
|
||||
self.store.users.get(&id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +39,12 @@ impl UserRepository {
|
||||
.bind(&user.username)
|
||||
.bind(&user.pub_key)
|
||||
.bind(&user.created_at)
|
||||
.execute(&self.db)
|
||||
.execute(&self.store.db)
|
||||
.await?;
|
||||
|
||||
// ajouter au cache
|
||||
let arc_server = Arc::new(user.clone());
|
||||
self.cache.insert_arc(user.id, arc_server.clone());
|
||||
self.store.users.insert_arc(user.id, arc_server.clone());
|
||||
|
||||
Ok(arc_server)
|
||||
}
|
||||
@@ -57,11 +56,11 @@ impl UserRepository {
|
||||
.bind(&user.username)
|
||||
.bind(&user.pub_key)
|
||||
.bind(&user.id)
|
||||
.execute(&self.db)
|
||||
.execute(&self.store.db)
|
||||
.await?;
|
||||
|
||||
// Mettre à jour le cache
|
||||
self.cache.insert(user.id, user.clone());
|
||||
self.store.users.insert(user.id, user.clone());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -69,28 +68,24 @@ impl UserRepository {
|
||||
pub async fn delete(&self, id: Uuid) -> Result<bool, sqlx::Error> {
|
||||
let rows_affected = sqlx::query("DELETE FROM user WHERE id = ?")
|
||||
.bind(&id)
|
||||
.execute(&self.db)
|
||||
.execute(&self.store.db)
|
||||
.await?
|
||||
.rows_affected();
|
||||
|
||||
if rows_affected > 0 {
|
||||
self.cache.remove(&id);
|
||||
self.store.users.remove(&id);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pour initialiser le cache depuis la DB
|
||||
pub async fn load_all_from_db(&self) -> Result<(), sqlx::Error> {
|
||||
let servers: Vec<User> = sqlx::query_as("SELECT * FROM user")
|
||||
.fetch_all(&self.db)
|
||||
.await?;
|
||||
|
||||
for server in servers {
|
||||
self.cache.insert(server.id, server);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
impl UserRepository {
|
||||
// getters (db)
|
||||
pub async fn db_all(&self) -> Result<Vec<User>, sqlx::Error> {
|
||||
sqlx::query_as("SELECT * FROM user")
|
||||
.fetch_all(&self.store.db)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
use sqlx::{AnyPool, SqlitePool};
|
||||
@@ -28,9 +29,9 @@ pub struct StoreService {
|
||||
pub sub_servers: SharedArcMap<Uuid, SubServer>,
|
||||
pub channels: SharedArcMap<Uuid, Channel>,
|
||||
pub sub_server_users: SharedArcVec<LinkSubServerUser>,
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl StoreService {
|
||||
pub async fn new(database_url: &str) -> Result<Self, sqlx::Error> {
|
||||
let connection_url = Self::normalize_database_url(database_url);
|
||||
@@ -38,9 +39,9 @@ impl StoreService {
|
||||
|
||||
let db = SqlitePool::connect(&connection_url).await?;
|
||||
|
||||
sqlx::migrate!("./src/store/migrations").run(&db).await?;
|
||||
// sqlx::migrate!("./src/store/migrations").run(&db).await?;
|
||||
|
||||
let service = Self {
|
||||
let mut service = Self {
|
||||
db,
|
||||
users: SharedArcMap::new(),
|
||||
sub_servers: SharedArcMap::new(),
|
||||
@@ -55,43 +56,56 @@ impl StoreService {
|
||||
}
|
||||
|
||||
async fn load_all_caches(&self) -> Result<(), sqlx::Error> {
|
||||
// Users
|
||||
let users: Vec<User> = sqlx::query_as("SELECT * FROM user")
|
||||
.fetch_all(&self.db)
|
||||
.await?;
|
||||
for user in users {
|
||||
self.users.insert(user.id, user);
|
||||
}
|
||||
let sub_server_rep = SubServerRepository::new(self.clone());
|
||||
let user_rep = UserRepository::new(self.clone());
|
||||
let channel_rep = ChannelRepository::new(self.clone());
|
||||
let link_sub_server_user_rep = LinkSubServerUserRepository::new(self.clone());
|
||||
|
||||
// SubServers
|
||||
let sub_servers: Vec<SubServer> = sqlx::query_as("SELECT * FROM sub_server")
|
||||
.fetch_all(&self.db)
|
||||
.await?;
|
||||
for sub_server in sub_servers {
|
||||
self.sub_servers.insert(sub_server.id, sub_server);
|
||||
}
|
||||
// sub_servers
|
||||
let sub_servers = sub_server_rep.db_all().await?;
|
||||
self.sub_servers.insert_batch_with_key(sub_servers, |sub_server| sub_server.id);
|
||||
|
||||
// Users
|
||||
let users = user_rep.db_all().await?;
|
||||
self.users.insert_batch_with_key(users, |user| user.id);
|
||||
|
||||
// Channels
|
||||
let channels: Vec<Channel> = sqlx::query_as("SELECT * FROM channel")
|
||||
.fetch_all(&self.db)
|
||||
.await?;
|
||||
for channel in channels {
|
||||
self.channels.insert(channel.id, channel);
|
||||
}
|
||||
let channels = channel_rep.db_all().await?;
|
||||
self.channels.insert_batch_with_key(channels, |channel| channel.id);
|
||||
|
||||
// Relations N-N
|
||||
let relations: Vec<LinkSubServerUser> = sqlx::query_as("SELECT * FROM sub_server_user")
|
||||
.fetch_all(&self.db)
|
||||
.await?;
|
||||
for relation in relations {
|
||||
self.sub_server_users.push(relation);
|
||||
}
|
||||
let relations: Vec<LinkSubServerUser> = link_sub_server_user_rep.db_all().await?;
|
||||
self.sub_server_users.extend(relations);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl StoreService {
|
||||
// Getters repositories
|
||||
pub fn user_repository(&self) -> UserRepository {
|
||||
UserRepository::new(self.clone())
|
||||
}
|
||||
|
||||
pub fn sub_server_repository(&self) -> SubServerRepository {
|
||||
SubServerRepository::new(self.clone())
|
||||
}
|
||||
|
||||
pub fn channel_repository(&self) -> ChannelRepository {
|
||||
ChannelRepository::new(self.clone())
|
||||
}
|
||||
|
||||
pub fn message_repository(&self) -> MessageRepository {
|
||||
MessageRepository::new(self.clone())
|
||||
}
|
||||
|
||||
pub fn sub_server_user_repository(&self) -> LinkSubServerUserRepository {
|
||||
LinkSubServerUserRepository::new(self.clone())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl StoreService {
|
||||
// ===== HELPERS =====
|
||||
/// ✅ Normalise l'URL pour supporter différentes bases de données
|
||||
|
||||
@@ -707,6 +707,38 @@ where
|
||||
let map_ref = self.inner.load_full();
|
||||
map_ref.values().cloned().collect::<Vec<_>>().into_iter()
|
||||
}
|
||||
|
||||
/// Insert une collection entière de paires clé-valeur
|
||||
pub fn insert_batch<I>(&self, items: I)
|
||||
where
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
let current = self.inner.load_full();
|
||||
let mut new_map = current.as_ref().clone();
|
||||
|
||||
for (key, value) in items {
|
||||
new_map.insert(key, value);
|
||||
}
|
||||
|
||||
self.inner.store(Arc::new(new_map));
|
||||
}
|
||||
|
||||
/// Insert une collection de valeurs avec une fonction pour extraire la clé
|
||||
pub fn insert_batch_with_key<I, F>(&self, items: I, key_fn: F)
|
||||
where
|
||||
I: IntoIterator<Item = V>,
|
||||
F: Fn(&V) -> K,
|
||||
{
|
||||
let current = self.inner.load_full();
|
||||
let mut new_map = current.as_ref().clone();
|
||||
|
||||
for value in items {
|
||||
let key = key_fn(&value);
|
||||
new_map.insert(key, value);
|
||||
}
|
||||
|
||||
self.inner.store(Arc::new(new_map));
|
||||
}
|
||||
}
|
||||
|
||||
// Clone gratuit (juste Arc::clone)
|
||||
@@ -1059,8 +1091,41 @@ where
|
||||
let map_ref = self.inner.load_full();
|
||||
map_ref.iter().map(|(k, v)| (k.clone(), v.clone())).collect::<Vec<_>>().into_iter()
|
||||
}
|
||||
|
||||
/// Insert une collection entière de paires clé-valeur
|
||||
pub fn insert_batch<I>(&self, items: I)
|
||||
where
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
let current = self.inner.load_full();
|
||||
let mut new_map = current.as_ref().clone();
|
||||
|
||||
for (key, value) in items {
|
||||
new_map.insert(key, Arc::new(value));
|
||||
}
|
||||
|
||||
self.inner.store(Arc::new(new_map));
|
||||
}
|
||||
|
||||
/// Insert une collection de valeurs avec une fonction pour extraire la clé
|
||||
pub fn insert_batch_with_key<I, F>(&self, items: I, key_fn: F)
|
||||
where
|
||||
I: IntoIterator<Item = V>,
|
||||
F: Fn(&V) -> K,
|
||||
{
|
||||
let current = self.inner.load_full();
|
||||
let mut new_map = current.as_ref().clone();
|
||||
|
||||
for value in items {
|
||||
let key = key_fn(&value);
|
||||
new_map.insert(key, Arc::new(value));
|
||||
}
|
||||
|
||||
self.inner.store(Arc::new(new_map));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===== IMPLÉMENTATIONS CLONE =====
|
||||
|
||||
impl<T> Clone for SharedArcVec<T> {
|
||||
|
||||
Reference in New Issue
Block a user