Last active
January 20, 2026 05:35
-
-
Save BrendanThompson/373026b909b918c4f6a013f415a1a88f to your computer and use it in GitHub Desktop.
Libsql why you no webpki
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class Database { | |
| var inner: libsql_database_t | |
| deinit { | |
| libsql_database_deinit(self.inner) | |
| } | |
| public func sync() throws { | |
| let sync = libsql_database_sync(self.inner) | |
| try errIf(sync.err) | |
| } | |
| public func connect() throws -> Connection { | |
| let conn = libsql_database_connect(self.inner) | |
| try errIf(conn.err) | |
| return Connection(from: conn) | |
| } | |
| public init( | |
| path: String, | |
| url: String, | |
| authToken: String, | |
| readYourWrites: Bool = true, | |
| encryptionKey: String? = nil, | |
| syncInterval: UInt64 = 0, | |
| withWebpki: Bool = false | |
| ) throws { | |
| self.inner = try path.withCString { path in | |
| try url.withCString { url in | |
| try authToken.withCString { authToken in | |
| try encryptionKey.withCString { encryptionKey in | |
| var desc = libsql_database_desc_t() | |
| desc.path = path | |
| desc.url = url | |
| desc.auth_token = authToken | |
| desc.encryption_key = encryptionKey | |
| desc.disable_read_your_writes = !readYourWrites | |
| desc.sync_interval = syncInterval | |
| desc.webpki = withWebpki | |
| let db = libsql_database_init(desc) | |
| try errIf(db.err) | |
| return db | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| typedef struct { | |
| libsql_error_t *err; | |
| void *inner; | |
| } libsql_database_t; | |
| typedef struct { | |
| /** The url to the primary database */ | |
| const char *url; | |
| /** Path to the database file or `:memory:` */ | |
| const char *path; | |
| /** Auth token to access the primary */ | |
| const char *auth_token; | |
| /** Encryption key to encrypt and decrypt the database in `path` */ | |
| const char *encryption_key; | |
| /** Interval to periodicaly sync with primary */ | |
| uint64_t sync_interval; | |
| /** Cypher to be used with `encryption_key` */ | |
| libsql_cypher_t cypher; | |
| /** If set, disable `read_your_writes`. To mantain consistency. */ | |
| bool disable_read_your_writes; | |
| /** Enable Webpki connector */ | |
| bool webpki; | |
| /** Offline writes */ | |
| bool synced; | |
| /** Safety assert */ | |
| bool disable_safety_assert; | |
| } libsql_database_desc_t; | |
| libsql_database_t libsql_database_init(libsql_database_desc_t desc); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[repr(C)] | |
| #[derive(Debug, Copy, Clone)] | |
| pub struct libsql_database_t { | |
| pub err: *mut libsql_error_t, | |
| pub inner: *mut ::std::os::raw::c_void, | |
| } | |
| #[no_mangle] | |
| #[signature(c)] | |
| pub extern "C" fn libsql_database_init(desc: c::libsql_database_desc_t) -> c::libsql_database_t { | |
| match (|| -> anyhow::Result<Database> { | |
| let path = desc | |
| .path | |
| .is_null() | |
| .not() | |
| .then(|| unsafe { CStr::from_ptr(desc.path) }); | |
| let url = desc | |
| .url | |
| .is_null() | |
| .not() | |
| .then(|| unsafe { CStr::from_ptr(desc.url) }); | |
| let auth_token = desc | |
| .auth_token | |
| .is_null() | |
| .not() | |
| .then(|| unsafe { CStr::from_ptr(desc.auth_token) }); | |
| let encryption_key = desc | |
| .encryption_key | |
| .is_null() | |
| .not() | |
| .then(|| unsafe { CStr::from_ptr(desc.encryption_key) }); | |
| let db = match (path, url, auth_token, desc.synced) { | |
| (None, None, None, _) => { | |
| let db = libsql::Builder::new_local(":memory:"); | |
| let db = unsafe { db.skip_safety_assert(desc.disable_safety_assert) }; | |
| RT.block_on(db.build()) | |
| } | |
| (Some(path), None, None, _) => { | |
| let db = libsql::Builder::new_local(path.to_str()?); | |
| let db = unsafe { db.skip_safety_assert(desc.disable_safety_assert) }; | |
| let db = match (desc.cypher, encryption_key) { | |
| ( | |
| c::libsql_cypher_t::LIBSQL_CYPHER_AES256 | |
| | c::libsql_cypher_t::LIBSQL_CYPHER_DEFAULT, | |
| Some(key), | |
| ) => db.encryption_config(libsql::EncryptionConfig { | |
| cipher: libsql::Cipher::Aes256Cbc, | |
| encryption_key: key.to_bytes().into(), | |
| }), | |
| _ => db, | |
| }; | |
| RT.block_on(async { | |
| let db = db.build().await?; | |
| let conn = db.connect()?; | |
| conn.query("PRAGMA journal_mode=WAL", ()).await?; | |
| Ok(db) | |
| }) | |
| } | |
| (None, Some(url), auth_token, _) => { | |
| let mut db = libsql::Builder::new_remote( | |
| url.to_str()?.to_string(), | |
| match auth_token { | |
| Some(auth_token) => auth_token.to_str()?.to_string(), | |
| None => "".to_string(), | |
| }, | |
| ); | |
| if desc.webpki { | |
| let connector = hyper_rustls::HttpsConnectorBuilder::new() | |
| .with_webpki_roots() | |
| .https_or_http() | |
| .enable_http1() | |
| .build(); | |
| db = db.connector(connector) | |
| }; | |
| let namespace = desc | |
| .namespace | |
| .is_null() | |
| .not() | |
| .then(|| unsafe { CStr::from_ptr(desc.namespace) }); | |
| if let Some(ns) = namespace { | |
| db = db.namespace(ns.to_str()?.to_string()); | |
| } | |
| RT.block_on(async { | |
| let version = VERSION.read().await; | |
| let db = if let Some(ref version) = *version { | |
| db.version(version.to_owned()) | |
| } else { | |
| db | |
| }; | |
| db.build().await | |
| }) | |
| } | |
| (Some(path), Some(url), auth_token, true) => { | |
| let db = libsql::Builder::new_synced_database( | |
| path.to_str()?, | |
| url.to_str()?.to_string(), | |
| match auth_token { | |
| Some(s) => s.to_str()?.to_string(), | |
| None => "".to_string(), | |
| }, | |
| ); | |
| let db = if desc.webpki { | |
| let connector = hyper_rustls::HttpsConnectorBuilder::new() | |
| .with_webpki_roots() | |
| .https_or_http() | |
| .enable_http1() | |
| .build(); | |
| db.connector(connector) | |
| } else { | |
| db | |
| }; | |
| RT.block_on(async { | |
| let version = VERSION.read().await; | |
| let db = if let Some(ref version) = *version { | |
| db.version(version.to_owned()) | |
| } else { | |
| db | |
| }; | |
| db.build().await | |
| }) | |
| } | |
| (Some(path), Some(url), auth_token, false) => { | |
| let db = libsql::Builder::new_remote_replica( | |
| path.to_str()?, | |
| url.to_str()?.to_string(), | |
| match auth_token { | |
| Some(s) => s.to_str()?.to_string(), | |
| None => "".to_string(), | |
| }, | |
| ); | |
| // NOTE: This is done so that the default zero initialization respects that | |
| // read_your_writes is true by default. | |
| let db = db.read_your_writes(desc.disable_read_your_writes.not()); | |
| let db = unsafe { db.skip_safety_assert(desc.disable_safety_assert) }; | |
| let db = match (desc.cypher, encryption_key) { | |
| ( | |
| c::libsql_cypher_t::LIBSQL_CYPHER_AES256 | |
| | c::libsql_cypher_t::LIBSQL_CYPHER_DEFAULT, | |
| Some(key), | |
| ) => db.encryption_config(libsql::EncryptionConfig { | |
| cipher: libsql::Cipher::Aes256Cbc, | |
| encryption_key: key.to_bytes().into(), | |
| }), | |
| _ => db, | |
| }; | |
| let db = if desc.sync_interval != 0 { | |
| db.sync_interval(Duration::from_millis(desc.sync_interval)) | |
| } else { | |
| db | |
| }; | |
| let db = if desc.webpki { | |
| let connector = hyper_rustls::HttpsConnectorBuilder::new() | |
| .with_webpki_roots() | |
| .https_or_http() | |
| .enable_http1() | |
| .build(); | |
| db.connector(connector) | |
| } else { | |
| db | |
| }; | |
| RT.block_on(async { | |
| let version = VERSION.read().await; | |
| let db = if let Some(ref version) = *version { | |
| db.version(version.to_owned()) | |
| } else { | |
| db | |
| }; | |
| db.build().await | |
| }) | |
| } | |
| _ => bail!("invalid database description"), | |
| }; | |
| Ok(db?) | |
| })() { | |
| Ok(db) => c::libsql_database_t { | |
| inner: Box::into_raw(Box::new(db)) as *mut c_void, | |
| ..Default::default() | |
| }, | |
| Err(err) => c::libsql_database_t { | |
| err: CString::new(err.to_string()).unwrap().into_raw() as *mut c::libsql_error_t, | |
| ..Default::default() | |
| }, | |
| } | |
| } | |
| #[doc = " Database description."] | |
| #[repr(C)] | |
| #[derive(Debug, Copy, Clone)] | |
| pub struct libsql_database_desc_t { | |
| #[doc = " The url to the primary database"] | |
| pub url: *const ::std::os::raw::c_char, | |
| #[doc = " Path to the database file or `:memory:`"] | |
| pub path: *const ::std::os::raw::c_char, | |
| #[doc = " Auth token to access the primary"] | |
| pub auth_token: *const ::std::os::raw::c_char, | |
| #[doc = " Encryption key to encrypt and decrypt the database in `path`"] | |
| pub encryption_key: *const ::std::os::raw::c_char, | |
| #[doc = " Interval to periodicaly sync with primary"] | |
| pub sync_interval: u64, | |
| #[doc = " Cypher to be used with `encryption_key`"] | |
| pub cypher: libsql_cypher_t, | |
| #[doc = " If set, disable `read_your_writes`. To mantain consistency."] | |
| pub disable_read_your_writes: bool, | |
| #[doc = " Enable Webpki connector"] | |
| pub webpki: bool, | |
| #[doc = " Offline writes"] | |
| pub synced: bool, | |
| #[doc = " Safety assert"] | |
| pub disable_safety_assert: bool, | |
| #[doc = " Provide a namespace through a header."] | |
| pub namespace: *const ::std::os::raw::c_char, | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment