// Copyright 2026 Leo Cheng
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// The two calling conventions a 3.0 server normalizes. `run_legacy` is the
/// synchronous core of ASGI 2.0's double-callable shape - `application(scope)`
/// returns an instance that folds the inbound stream - and it yields exactly
/// what the single-callable `run_http` yields. The async lifts a real server
/// binds to (`to_asgi`, `double_to_single_callable`, `guarantee_single_callable`
/// over `AsgiApplication`) are constructed here; running one needs an async
/// runtime, so the synchronous cores above stand in for their semantics.
///
/// moon run src/examples/13-legacy
#coverage.skip
fn main {
let handler : @moonasgi.Handler = fn(req) {
@moonasgi.Response::text("legacy \{req.http_method} \{req.path}")
}
let scope = @moonasgi.Scope::Http(
@moonasgi.HttpScope::new(http_method="POST", path="/l"),
)
let inbound = [@spec.HttpRequest(body=b"heke1228", more_body=false)]
// The double-callable convention, run synchronously: the outer call takes the
// scope, the returned instance folds the inbound event stream.
let out = @moonasgi.run_legacy(
fn(sc) { fn(inb) { @moonasgi.run_http(handler, sc, inb) } },
scope,
inbound,
)
for ev in out {
match ev {
@spec.HttpResponseStart(status~, ..) => println("start -> \{status}")
@spec.HttpResponseBody(body~, ..) =>
println("body -> " + @moonasgi.latin1_decode(body))
_ => ()
}
}
let single = @moonasgi.run_http(handler, scope, inbound)
println("legacy == single-callable: \{out == single}")
// The async lifts a server binds to, constructed (not run) at the seam.
let legacy_app : @moonasgi.LegacyAsgiApp = fn(_sc) { fn(_recv, _send) { } }
let _ : @moonasgi.AsgiApp = @moonasgi.double_to_single_callable(legacy_app)
let _ : @moonasgi.AsgiApp = @moonasgi.guarantee_single_callable(
@moonasgi.AsgiApplication::Single(@moonasgi.to_asgi(handler)),
)
let _ : @moonasgi.AsgiApp = @moonasgi.guarantee_single_callable(
@moonasgi.AsgiApplication::Legacy(legacy_app),
)
println(
"async lifts constructed: to_asgi, double_to_single_callable, guarantee_single_callable",
)
}