Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

@@ -0,0 +1,13 @@
type Identity {
id: Text
user_id: model.id?
tenant_id: model.id?
}
verify(claims: dever.auth.Claims) (identity: Identity) {
identity = Identity {
id = claims.subject
user_id = null
tenant_id = null
}
}
@@ -0,0 +1,3 @@
global type Auth {
label: Text(1, 64)
}
@@ -0,0 +1,3 @@
public post echo = app.echo
public post raw = app.raw
@@ -0,0 +1,19 @@
type Row {
id: Int
text: Text
weight: Float
note: Text?
}
type Payload {
rows: List<Row>
raw: Json
}
echo(payload: Payload) (value: Payload) {
value = payload
}
raw(source: Json) (value: Json) {
value = source
}
@@ -0,0 +1,51 @@
use std::io::Write;
use std::path::Path;
use dever_backend_bridge::{Target, emit_object};
use dever_core::source::SourceMap;
use dever_runtime::config::Settings;
fn main() -> Result<(), String> {
let arguments = std::env::args_os().skip(1).collect::<Vec<_>>();
let (project, output, ir) = match arguments.as_slice() {
[project, output] => (project, output, None),
[project, output, ir] => (project, output, Some(ir)),
_ => {
return Err("usage: api-json-object <project> <new-object-file> [new-ir-file]".into());
}
};
let project = Path::new(project);
let sources =
SourceMap::load(&project.join("module")).map_err(|errors| format!("{errors:?}"))?;
let settings = Settings::load_project(project).map_err(|error| error.to_string())?;
let program = dever_core::check_with_settings(&sources, &settings).map_err(|errors| {
errors
.iter()
.map(|error| error.render(&sources))
.collect::<String>()
})?;
let errors = program.application_errors()?;
if !errors.is_empty() {
return Err(errors
.iter()
.map(|error| error.render(&sources))
.collect::<String>());
}
let module = dever_core::llvm::emit_executable(&program, &sources)?;
if let Some(ir) = ir {
let mut ir = std::fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(ir)
.map_err(|error| error.to_string())?;
ir.write_all(module.as_bytes())
.map_err(|error| error.to_string())?;
}
let object = emit_object(&module, Target::LinuxX86_64)?;
let mut output = std::fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(output)
.map_err(|error| error.to_string())?;
output.write_all(&object).map_err(|error| error.to_string())
}
+115
View File
@@ -0,0 +1,115 @@
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
"os/signal"
"runtime"
"syscall"
"time"
)
type row struct {
ID int64 `json:"id"`
Text string `json:"text"`
Weight float64 `json:"weight"`
Note *string `json:"note"`
}
type payload struct {
Rows []row `json:"rows"`
Raw json.RawMessage `json:"raw"`
}
type envelope struct {
Code int `json:"code"`
Message string `json:"message"`
Data any `json:"data"`
}
func handle(writer http.ResponseWriter, request *http.Request) {
typed := request.URL.Path == "/benchmark/echo/echo"
if request.Method != http.MethodPost || (!typed && request.URL.Path != "/benchmark/echo/raw") {
http.NotFound(writer, request)
return
}
body := http.MaxBytesReader(writer, request.Body, 16*1024*1024)
defer body.Close()
decoder := json.NewDecoder(body)
decoder.DisallowUnknownFields()
var result any
var err error
if typed {
var input struct {
Payload payload `json:"payload"`
}
err = decoder.Decode(&input)
result = input.Payload
} else {
var input struct {
Source json.RawMessage `json:"source"`
}
err = decoder.Decode(&input)
result = input.Source
}
var extra any
if err != nil || decoder.Decode(&extra) != io.EOF {
http.Error(writer, "invalid JSON", http.StatusBadRequest)
return
}
encoded, err := json.Marshal(envelope{0, "ok", result})
if err != nil {
http.Error(writer, "invalid response", http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Type", "application/json")
writer.Write(encoded)
}
func run() error {
runtime.GOMAXPROCS(1)
content, err := os.ReadFile("config/setting.json")
if err != nil {
return err
}
var settings struct {
HTTP struct {
Port uint16 `json:"port"`
} `json:"http"`
}
if err := json.Unmarshal(content, &settings); err != nil {
return err
}
listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", settings.HTTP.Port))
if err != nil {
return err
}
server := &http.Server{Handler: http.HandlerFunc(handle), ReadHeaderTimeout: 10 * time.Second, IdleTimeout: 10 * time.Second}
stopping := make(chan os.Signal, 1)
signal.Notify(stopping, syscall.SIGTERM)
defer signal.Stop(stopping)
closed := make(chan error, 1)
go func() {
<-stopping
context, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
closed <- server.Shutdown(context)
}()
if err := server.Serve(listener); !errors.Is(err, http.ErrServerClosed) {
return err
}
return <-closed
}
func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
+131
View File
@@ -0,0 +1,131 @@
use std::convert::Infallible;
use std::time::Duration;
use bytes::Bytes;
use http_body_util::{BodyExt, Full, Limited};
use hyper::{
Request, Response, StatusCode, body::Incoming, server::conn::http1, service::service_fn,
};
use hyper_util::rt::TokioIo;
use serde::{Deserialize, Serialize};
use serde_json::value::RawValue;
use tokio::net::TcpListener;
use tokio::signal::unix::{SignalKind, signal};
use tokio::sync::watch;
use tokio::task::JoinSet;
#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
struct Row {
id: i64,
text: String,
weight: f64,
note: Option<String>,
}
#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
struct Payload {
rows: Vec<Row>,
raw: Box<RawValue>,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct TypedRequest {
payload: Payload,
}
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct RawRequest {
source: Box<RawValue>,
}
#[derive(Serialize)]
struct Envelope<Value> {
code: u8,
message: &'static str,
data: Value,
}
async fn handle(request: Request<Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
let typed = request.uri().path() == "/benchmark/echo/echo";
if request.method() != hyper::Method::POST
|| !typed && request.uri().path() != "/benchmark/echo/raw"
{
return Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Full::new(Bytes::new()))
.unwrap());
}
let body = Limited::new(request.into_body(), 16 * 1024 * 1024)
.collect()
.await;
let encoded = body.map_err(|error| error.to_string()).and_then(|body| {
let bytes = body.to_bytes();
if typed {
serde_json::from_slice::<TypedRequest>(&bytes).and_then(|value| {
serde_json::to_vec(&Envelope {
code: 0,
message: "ok",
data: value.payload,
})
})
} else {
serde_json::from_slice::<RawRequest>(&bytes).and_then(|value| {
serde_json::to_vec(&Envelope {
code: 0,
message: "ok",
data: value.source,
})
})
}
.map_err(|error| error.to_string())
});
let (status, body) = match encoded {
Ok(body) => (StatusCode::OK, body),
Err(_) => (StatusCode::BAD_REQUEST, Vec::new()),
};
Ok(Response::builder()
.status(status)
.header("Content-Type", "application/json")
.body(Full::new(Bytes::from(body)))
.unwrap())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio::runtime::Builder::new_current_thread().enable_all().build()?.block_on(async {
let settings: serde_json::Value = serde_json::from_slice(&std::fs::read("config/setting.json")?)?;
let port = u16::try_from(settings["http"]["port"].as_u64().ok_or("missing port")?)?;
let listener = TcpListener::bind(("127.0.0.1", port)).await?;
let mut terminate = signal(SignalKind::terminate())?;
let (shutdown, stopping) = watch::channel(false);
let mut connections = JoinSet::new();
loop {
tokio::select! {
_ = terminate.recv() => break,
Some(result) = connections.join_next(), if !connections.is_empty() => { result?; },
accepted = listener.accept() => {
let (stream, _) = accepted?;
stream.set_nodelay(true)?;
let mut stopping = stopping.clone();
connections.spawn(async move {
let connection = http1::Builder::new().serve_connection(TokioIo::new(stream), service_fn(handle));
tokio::pin!(connection);
tokio::select! {
_ = &mut connection => {},
_ = stopping.changed() => {
connection.as_mut().graceful_shutdown();
let _ = tokio::time::timeout(Duration::from_secs(2), connection).await;
}
}
});
}
}
}
shutdown.send(true)?;
while let Some(result) = connections.join_next().await { result?; }
Ok(())
})
}
@@ -0,0 +1,246 @@
use dever_runtime::api;
use dever_runtime::application::Session;
use dever_runtime::auth;
use dever_runtime::config::RuntimeProfile;
use dever_runtime::http::{Request, Response};
use dever_runtime::wire::decode::{self, Fields, Reader};
use dever_runtime::wire::{Encoded, Encoder};
use dever_runtime::{lifecycle, task};
#[derive(Default)]
struct Row {
id: i64,
text: String,
weight: f64,
note: Option<String>,
}
impl Fields for Row {
fn count(&self) -> usize {
4
}
fn index(&self, name: &str) -> Result<usize, String> {
match name {
"id" => Ok(0),
"text" => Ok(1),
"weight" => Ok(2),
"note" => Ok(3),
_ => Err("unknown wire record field".into()),
}
}
fn required(&self, index: usize) -> bool {
index != 3
}
fn read(&mut self, index: usize, reader: &mut Reader<'_, '_>) -> Result<(), String> {
match index {
0 => self.id = reader.int()?,
1 => self.text = reader.text()?.into_owned(),
2 => self.weight = reader.float()?,
3 => {
reader.nullable(&mut |reader| {
self.note = Some(reader.text()?.into_owned());
Ok(())
})?;
}
_ => return Err("invalid wire field index".into()),
}
Ok(())
}
}
#[derive(Default)]
struct Payload {
rows: Vec<Row>,
raw: Option<Encoded>,
}
impl Fields for Payload {
fn count(&self) -> usize {
2
}
fn index(&self, name: &str) -> Result<usize, String> {
match name {
"rows" => Ok(0),
"raw" => Ok(1),
_ => Err("unknown wire record field".into()),
}
}
fn required(&self, _: usize) -> bool {
true
}
fn read(&mut self, index: usize, reader: &mut Reader<'_, '_>) -> Result<(), String> {
match index {
0 => reader.list(&mut |reader| {
let mut row = Row::default();
reader.record(&mut row)?;
self.rows.push(row);
Ok(())
}),
1 => {
self.raw = Some(reader.json()?);
Ok(())
}
_ => Err("invalid wire field index".into()),
}
}
}
impl Payload {
fn encode(self) -> Result<Encoded, String> {
let mut encoder = Encoder::default();
encoder.compiled_record(2, |encoder| {
encoder.compiled_key("\"rows\":")?;
encoder.begin_array()?;
for row in self.rows {
encoder.compiled_record(4, |encoder| {
encoder.compiled_key("\"id\":")?;
encoder.int(row.id)?;
encoder.compiled_key(",\"text\":")?;
encoder.text(&row.text)?;
encoder.compiled_key(",\"weight\":")?;
encoder.float(row.weight)?;
encoder.compiled_key(",\"note\":")?;
match row.note {
Some(note) => encoder.text(&note),
None => encoder.null(),
}
})?;
}
encoder.end()?;
encoder.compiled_key(",\"raw\":")?;
encoder.encoded(&self.raw.ok_or("missing required wire field")?)
})?;
encoder.finish()
}
}
enum Value {
Typed(Payload),
Raw(Encoded),
}
struct Arguments {
typed: bool,
value: Option<Value>,
}
impl Fields for Arguments {
fn count(&self) -> usize {
1
}
fn index(&self, name: &str) -> Result<usize, String> {
if name == if self.typed { "payload" } else { "source" } {
Ok(0)
} else {
Err("unknown wire record field".into())
}
}
fn required(&self, _: usize) -> bool {
true
}
fn read(&mut self, _: usize, reader: &mut Reader<'_, '_>) -> Result<(), String> {
self.value = Some(if self.typed {
let mut payload = Payload::default();
reader.record(&mut payload)?;
Value::Typed(payload)
} else {
Value::Raw(reader.json()?)
});
Ok(())
}
}
async fn call(mut request: Request, typed: bool) -> Response {
if let Err(error) = auth::require_components(&[], &[]).await {
return api::auth_error(error);
}
if let Err(error) = api::upload::read_body(&mut request).await {
return api::invalid_input(error);
}
let body = match api::Inputs::json_body(&request) {
Ok(body) => body,
Err(error) => return api::invalid_input(error),
};
let mut arguments = Arguments { typed, value: None };
if let Err(error) = decode::read(body, &mut |reader| reader.record(&mut arguments)) {
return api::invalid_input(api::InputError(error));
}
let encoded = match arguments.value {
Some(Value::Typed(payload)) => payload.encode(),
Some(Value::Raw(value)) => Ok(value),
None => Err("missing required wire field".into()),
};
match encoded {
Ok(value) => {
if api::commit_response_metadata().is_err() {
return api::internal_error();
}
api::success(value)
}
Err(_) => api::internal_error(),
}
}
async fn route(request: Request) -> Result<Response, String> {
let typed = match request.target.split('?').next().unwrap_or("") {
"/benchmark/echo/echo" => true,
"/benchmark/echo/raw" => false,
_ => return Ok(api::not_found()),
};
if request.method != "POST" {
return Ok(api::method_not_allowed(&["POST"]));
}
let prepared = match auth::prepare(&[], &request, true) {
Ok(prepared) => prepared,
Err(error) => return Ok(api::auth_error(error)),
};
let identity = prepared.claims().map(|claims| auth::Identity {
id: claims.subject.clone(),
user_id: None,
tenant_id: None,
});
Ok(
match auth::scope(prepared, identity, call(request, typed)).await {
Ok(response) => response,
Err(error) => api::auth_error(error),
},
)
}
fn main() -> Result<(), String> {
let session = Session::load(
RuntimeProfile {
sqlite: true,
postgres: false,
},
&[(None, "benchmark", false)],
&[],
)?;
session.initialize_authorization(false)?;
let cleanup = session.clone();
task::run_entry_with_typed_cleanup(
task::RuntimeConfig::default(),
session.clone().scope(async move {
session
.databases()
.prepare()
.await
.map_err(|error| error.to_string())?;
lifecycle::configure(true, false)?;
lifecycle::run(api::serve(route)).await
}),
|result| async move {
let closed = cleanup.close().await;
result.and(closed)
},
)
}
@@ -0,0 +1,112 @@
#define _POSIX_C_SOURCE 200809L
#include "runtime.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
extern long long dever_test_allocations(void);
static void text_clone(const void *source, void *target) {
*(void **)target = dever_rt_v1_text_retain(*(void *const *)source);
}
static void text_drop(void *value) {
dever_rt_v1_text_release(*(void **)value);
*(void **)value = NULL;
}
static uint8_t text_equal(const void *left, const void *right) {
return dever_rt_v1_text_equal(*(void *const *)left, *(void *const *)right);
}
static const DeverRtType text_type = {
sizeof(void *), _Alignof(void *), text_clone, text_drop, text_equal, NULL
};
static uint32_t input_field(void *inputs, void *out, DeverRtBuffer *error) {
const DeverRtWireName name = {(const uint8_t *)"source", 6};
uint8_t present = 0;
return dever_rt_v1_cmd_input_field(inputs, &name, 1, out, &present, error);
}
static uint32_t decode(const void *reader, void *out, DeverRtBuffer *error) {
return dever_rt_v1_wire_read_raw(reader, out, error);
}
static uint32_t encode(const void *value, void *encoder, DeverRtBuffer *error) {
return dever_rt_v1_wire_encoder_json(encoder, *(void *const *)value, error);
}
static uint32_t operation(unsigned phase, void *body, void *source, void **out, DeverRtBuffer *error) {
if (phase == 0) return dever_rt_v1_cmd_decode(body, &text_type, input_field, out, error);
if (phase == 1) return dever_rt_v1_wire_decode(source, &text_type, decode, out, error);
if (phase == 2) return dever_rt_v1_wire_encode(&source, &text_type, encode, out, error);
return dever_rt_v1_json_from_text(source, out, error);
}
int dever_test_run(void) {
const char *setting = getenv("DEVER_WIRE_BENCH_ROWS");
size_t rows = setting == NULL ? 128 : (size_t)strtoul(setting, NULL, 10);
int wide = getenv("DEVER_WIRE_BENCH_WIDE") != NULL;
if (rows != 1 && rows != 16 && rows != 128 && !(wide && rows == 1024)) return 1;
const char *row = "{\"id\":9007199254740993,\"text\":\"雪😀\\n\\\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"weight\":1.25,\"note\":null}";
const char *suffix = "],\"raw\":{\"large\":123456789012345678901234567890}}";
size_t capacity = rows * (strlen(row) + 1) + strlen(suffix) + 64;
char *raw = malloc(capacity);
if (raw == NULL) return 2;
strcpy(raw, wide ? "{" : "{\"rows\":[");
for (size_t index = 0; index < rows; ++index) {
if (index != 0) strcat(raw, ",");
if (wide) {
char field[64];
snprintf(field, sizeof(field), "\"field_%zu\":%zu", index, index);
strcat(raw, field);
} else {
strcat(raw, row);
}
}
strcat(raw, wide ? "}" : suffix);
size_t length = strlen(raw);
DeverRtBuffer error = {0};
void *source = NULL, *body = NULL;
if (dever_rt_v1_text_new((const uint8_t *)raw, length, &source, &error)) return 3;
if (getenv("DEVER_WIRE_BENCH_VALIDATED") != NULL) {
void *validated = NULL;
if (dever_rt_v1_wire_decode(source, &text_type, decode, &validated, &error)) return 11;
dever_rt_v1_text_release(source);
source = validated;
}
char *request = malloc(length + 12);
if (request == NULL) return 4;
snprintf(request, length + 12, "{\"source\":%s}", raw);
if (dever_rt_v1_text_new((const uint8_t *)request, strlen(request), &body, &error)) return 5;
free(request);
for (unsigned phase = 0; phase < 4; ++phase) {
void *output = NULL;
if (operation(phase, body, source, &output, &error)) return 6;
DeverRtBuffer bytes = {0};
if (dever_rt_v1_text_export(output, &bytes) || bytes.len != length || memcmp(bytes.ptr, raw, length) != 0) return 7;
dever_rt_v1_buffer_free(bytes.ptr, bytes.len);
dever_rt_v1_text_release(output);
struct timespec started, finished;
if (clock_gettime(CLOCK_MONOTONIC, &started)) return 8;
long long allocations = dever_test_allocations();
const size_t iterations = 500;
for (size_t iteration = 0; iteration < iterations; ++iteration) {
if (operation(phase, body, source, &output, &error)) return 9;
dever_rt_v1_text_release(output);
}
allocations = dever_test_allocations() - allocations;
if (clock_gettime(CLOCK_MONOTONIC, &finished)) return 10;
int64_t elapsed = (int64_t)(finished.tv_sec - started.tv_sec) * INT64_C(1000000000)
+ finished.tv_nsec - started.tv_nsec;
printf("{\"phase\":%u,\"rows\":%zu,\"iterations\":%zu,\"elapsed_ns\":%lld,\"allocations\":%lld}\n",
phase, rows, iterations, (long long)elapsed, allocations);
}
dever_rt_v1_text_release(source);
dever_rt_v1_text_release(body);
free(raw);
return 0;
}
@@ -0,0 +1,135 @@
#define _POSIX_C_SOURCE 200809L
#include "runtime.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
extern long long dever_test_allocations(void);
#ifndef WIRE_TEXT_KEY
#define WIRE_TEXT_KEY "text"
#endif
#ifndef WIRE_NUMBER_KEY
#define WIRE_NUMBER_KEY "number"
#endif
#ifndef WIRE_RECORD
#define WIRE_RECORD 0
#endif
typedef struct {
void *text;
int64_t rows;
} Payload;
#if WIRE_RECORD != 2
static const DeverRtWireName fields[] = {
{(const uint8_t *)WIRE_TEXT_KEY, sizeof(WIRE_TEXT_KEY) - 1},
{(const uint8_t *)WIRE_NUMBER_KEY, sizeof(WIRE_NUMBER_KEY) - 1}
};
#endif
static void payload_clone(const void *source, void *destination) {
const Payload *input = source;
Payload *output = destination;
*output = *input;
output->text = dever_rt_v1_text_retain(input->text);
}
static void payload_drop(void *value) {
Payload *payload = value;
dever_rt_v1_text_release(payload->text);
payload->text = NULL;
}
static uint8_t payload_equal(const void *left, const void *right) {
const Payload *first = left;
const Payload *second = right;
return first->rows == second->rows && dever_rt_v1_text_equal(first->text, second->text);
}
static const DeverRtType payload_type = {
sizeof(Payload), _Alignof(Payload), payload_clone, payload_drop, payload_equal, NULL
};
#if WIRE_RECORD == 2
static const DeverRtWireName prefixes[] = {
{(const uint8_t *)"\"" WIRE_TEXT_KEY "\":", sizeof("\"" WIRE_TEXT_KEY "\":") - 1},
{(const uint8_t *)",\"" WIRE_NUMBER_KEY "\":", sizeof(",\"" WIRE_NUMBER_KEY "\":") - 1}
};
static uint32_t encode_fields(const void *value, void *writer, DeverRtBuffer *error) {
const Payload *payload = value;
uint32_t status = dever_rt_v1_wire_encoder_compiled_key(writer, &prefixes[0], error);
if (status == 0) status = dever_rt_v1_wire_encoder_text(writer, payload->text, error);
if (status == 0) status = dever_rt_v1_wire_encoder_compiled_key(writer, &prefixes[1], error);
if (status == 0) status = dever_rt_v1_wire_encoder_int(writer, INT64_C(9007199254740993), error);
return status;
}
#elif WIRE_RECORD
static uint32_t encode_field(uint64_t index, const void *value, void *writer, DeverRtBuffer *error) {
const Payload *payload = value;
if (index == 0) return dever_rt_v1_wire_encoder_text(writer, payload->text, error);
if (index == 1) return dever_rt_v1_wire_encoder_int(writer, INT64_C(9007199254740993), error);
return 2;
}
#endif
static uint32_t encode(const void *value, void *writer, DeverRtBuffer *error) {
const Payload *payload = value;
uint32_t status = dever_rt_v1_wire_encoder_begin_array(writer, error);
for (int64_t index = 0; index < payload->rows && status == 0; ++index) {
#if WIRE_RECORD == 2
status = dever_rt_v1_wire_encoder_compiled_record(writer, value, &payload_type, 2, encode_fields, error);
#elif WIRE_RECORD
status = dever_rt_v1_wire_encoder_record(writer, value, &payload_type, fields, 2, encode_field, error);
#else
status = dever_rt_v1_wire_encoder_begin_object(writer, error);
if (status == 0) status = dever_rt_v1_wire_encoder_key(writer, &fields[0], error);
if (status == 0) status = dever_rt_v1_wire_encoder_text(writer, payload->text, error);
if (status == 0) status = dever_rt_v1_wire_encoder_key(writer, &fields[1], error);
if (status == 0) status = dever_rt_v1_wire_encoder_int(writer, INT64_C(9007199254740993), error);
if (status == 0) status = dever_rt_v1_wire_encoder_end(writer, error);
#endif
}
if (status == 0) status = dever_rt_v1_wire_encoder_end(writer, error);
return status;
}
int dever_test_run(void) {
const char *configured = getenv("DEVER_WIRE_BENCH_ROWS");
int64_t rows = configured == NULL ? 128 : strtoll(configured, NULL, 10);
if (rows != 4 && rows != 128) return 1;
const char *text = "Unicode 雪😀 and newline\n";
const char *row = "{\"" WIRE_TEXT_KEY "\":\"Unicode 雪😀 and newline\\n\",\"" WIRE_NUMBER_KEY "\":9007199254740993}";
Payload payload = {NULL, rows};
DeverRtBuffer error = {0};
if (dever_rt_v1_text_new((const uint8_t *)text, strlen(text), &payload.text, &error)) return 2;
void *output = NULL;
if (dever_rt_v1_wire_encode(&payload, &payload_type, encode, &output, &error)) return 3;
DeverRtBuffer bytes = {0};
if (dever_rt_v1_text_export(output, &bytes)) return 4;
size_t row_length = strlen(row);
if (bytes.len != 1 + (row_length + 1) * (size_t)rows || bytes.ptr[0] != '[' || bytes.ptr[bytes.len - 1] != ']') return 5;
for (int64_t index = 0; index < rows; ++index) {
if (memcmp(bytes.ptr + 1 + (size_t)index * (row_length + 1), row, row_length) != 0) return 6;
}
dever_rt_v1_buffer_free(bytes.ptr, bytes.len);
dever_rt_v1_text_release(output);
struct timespec started, finished;
if (clock_gettime(CLOCK_MONOTONIC, &started)) return 7;
long long allocations = dever_test_allocations();
const int64_t iterations = 500;
for (int64_t iteration = 0; iteration < iterations; ++iteration) {
if (dever_rt_v1_wire_encode(&payload, &payload_type, encode, &output, &error)) return 8;
dever_rt_v1_text_release(output);
}
allocations = dever_test_allocations() - allocations;
if (clock_gettime(CLOCK_MONOTONIC, &finished)) return 9;
int64_t elapsed = (int64_t)(finished.tv_sec - started.tv_sec) * INT64_C(1000000000)
+ finished.tv_nsec - started.tv_nsec;
payload_drop(&payload);
printf("{\"rows\":%lld,\"iterations\":%lld,\"elapsed_ns\":%lld,\"allocations\":%lld}\n",
(long long)rows, (long long)iterations, (long long)elapsed, allocations);
return 0;
}