/
nv-lang
/
nova-http
Обзор
Документация
Войти
/
nv-lang
/
nova-http
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
src/message.nv
136 строк
6 KB
Evgeniy Golovin
style(225.1): вертикальный ритм — sweep классов a/b/e (src)
26 июл 2026, 02:21
26 июл 2026, 02:21
d0e6b36
Код
Авторство
О чём код?
// SPDX-License-Identifier: MIT OR Apache-2.0 // nova-http: message.nv — Request / Response value-модель (D358). Extracted // from monorepo std/http (Plan 203 Ф.1). // // `Request`/`Response` несут must-consume `Body` (D359) → сами линейны (`consume`): // незакрытый Request/Response = compile-error (обязательство «тело должно быть // разряжено» распространяется на всю запись). Метаданные (method/url/version/ // status/headers) читаются borrow-методами; ТЕЛО разряжается ДЕЛЕГИРУЮЩИМИ // consume-методами (`resp.into_text()` → `@body.into_text()`, reqwest-эргономика; consume- // поле дренируется in-place — D133-модель `@file.close()`). // // КОНСТРУИРОВАНИЕ (ограничение D133, verified): запись с consume-полем строится // ТОЛЬКО с полем-значением как СВЕЖИМ inline-выражением (не переменной/параметром) // → конструкторы принимают СЫРЬЁ тела (`[]u8` / `BodyReader`) и собирают `Body` // внутри (`.to_body()`/`.into_body()` inline). Pre-built `Body` в конструктор передать // нельзя (move consume-переменной в поле не распознаётся). `[M-178-consume-field-ctor-from-var]` // // Builder-эргономика (RequestBuilder / ResponseBuilder / verb one-shots) и // `error_for_status` — Ф.2 (client). `[M-178-message-builders]` module http /// HTTP-запрос: метод + URL + версия + заголовки + must-consume тело. #stable(since = "0.1") export type Request consume { ro method Method ro url Url ro version Version ro headers HeaderMap consume body Body } /// Построить запрос с in-memory телом (HTTP/1.1). `body_bytes` — сырьё тела. #stable(since = "0.1") export fn Request.new(method Method, url Url, headers HeaderMap, consume body_bytes []u8) -> Request => { method, url, version: Version.Http11, headers, body: body_bytes.into_body() } /// Построить запрос без тела (GET/HEAD). #stable(since = "0.1") export fn Request.empty(method Method, url Url, headers HeaderMap) -> Request => { method, url, version: Version.Http11, headers, body: Body.empty() } /// Построить запрос с потоковым телом (Ф.1: in-memory reader). #stable(since = "0.1") export fn Request.streaming(method Method, url Url, headers HeaderMap, reader BodyReader) -> Request => { method, url, version: Version.Http11, headers, body: reader.into_body() } /// Метод (borrow). #stable(since = "0.1") export fn Request @method() -> Method => @method /// URL (borrow). #stable(since = "0.1") export fn Request @url() -> Url => @url /// Версия (borrow). #stable(since = "0.1") export fn Request @version() -> Version => @version /// Заголовки (borrow). #stable(since = "0.1") export fn Request @headers() -> HeaderMap => @headers /// Разрядить тело → байты (потребляет Request). #stable(since = "0.1") export fn Request consume @into_body_bytes() -> Result[[]u8, HttpError] { @body.into_bytes() } /// Дочитать и отбросить тело (потребляет Request). #stable(since = "0.1") export fn Request consume @drain() -> Result[(), HttpError] { @body.drain() } /// Взять потоковый ридер тела (потребляет Request). #stable(since = "0.1") export fn Request consume @into_reader() -> BodyReader { @body.into_reader() } /// HTTP-ответ: версия + статус + заголовки + must-consume тело. #stable(since = "0.1") export type Response consume { ro version Version ro status StatusCode ro headers HeaderMap consume body Body } /// Построить ответ с in-memory телом (HTTP/1.1). `body_bytes` — сырьё тела. #stable(since = "0.1") export fn Response.new(status StatusCode, headers HeaderMap, consume body_bytes []u8) -> Response => { version: Version.Http11, status, headers, body: body_bytes.into_body() } /// Построить ответ с явной версией + in-memory телом (Ф.2 client parse-result). #stable(since = "0.1") export fn Response.new(version Version, status StatusCode, headers HeaderMap, consume body_bytes []u8) -> Response => { version, status, headers, body: body_bytes.into_body() } /// Построить ответ без тела (204/304). #stable(since = "0.1") export fn Response.empty(status StatusCode, headers HeaderMap) -> Response => { version: Version.Http11, status, headers, body: Body.empty() } /// Построить ответ с потоковым телом (Ф.1: in-memory reader; Ф.2: transport). #stable(since = "0.1") export fn Response.streaming(status StatusCode, headers HeaderMap, reader BodyReader) -> Response => { version: Version.Http11, status, headers, body: reader.into_body() } /// Статус (borrow). #stable(since = "0.1") export fn Response @status() -> StatusCode => @status /// Версия (borrow). #stable(since = "0.1") export fn Response @version() -> Version => @version /// Заголовки (borrow). #stable(since = "0.1") export fn Response @headers() -> HeaderMap => @headers /// 2xx? (borrow). #stable(since = "0.1") export fn Response @is_success() -> bool => @status.is_success() /// Разрядить тело → байты (с max-guard; потребляет Response). Единственный способ /// достать тело — must-consume. #stable(since = "0.1") export fn Response consume @into_bytes() -> Result[[]u8, HttpError] { @body.into_bytes() } /// Разрядить тело → UTF-8 строка (потребляет Response). #stable(since = "0.1") export fn Response consume @into_text() -> Result[str, HttpError] { @body.into_text() } /// Дочитать и отбросить тело → conn в пул (потребляет Response). #stable(since = "0.1") export fn Response consume @drain() -> Result[(), HttpError] { @body.drain() } /// Взять потоковый ридер тела (потребляет Response; ручной pull). #stable(since = "0.1") export fn Response consume @into_reader() -> BodyReader { @body.into_reader() }