Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-mcp

Model Context Protocol server for Pudu language documentation and compiler tools

0.1.1Apache-2.01

InstallClose

Pagination.pudu

Pudu42 lines1.5 KB

GitHub ↗
1/** @Domain.Protocol.Pagination.Module — opaque cursors over list results */2module PuduLangMcp.Domain.Protocol.Pagination34import Std.Json as Json5import Std.Math as Math6import Std.Text as Text7import PuduLangMcp.Errors.RpcError as RpcError8import PuduLangMcp.Utils.JsonAccess as Access910/// What every cursor this server issues begins with.11const CURSOR_PREFIX: Str = "offset:"1213/// The `cursor` parameter, when there is one.14export fn cursorOf(params: &Json.Json) -> Result[Option[Str], RpcError.ProtocolError] {15  match Access.member(params, "cursor") {16    case None => Ok(None)17    case Some(Json.Text(cursor)) => Ok(Some(cursor))18    case Some(_) => Err(RpcError.InvalidParams("cursor must be a string"))19  }20}2122/// One page of a list and the cursor of the next, if any remain.23export fn page[T](items: &Array[T], cursor: &Option[Str], size: Int) -> Result[(Array[T], Option[Str]), RpcError.ProtocolError] {24  let start = match cursor {25    case None => 026    case Some(text) => match offsetOf(text, items.length()) {27      case Some(offset) => offset28      case None => { return Err(RpcError.InvalidParams("invalid cursor")) }29    }30  }31  let end = Math.min(start + size, items.length())32  let next = if end < items.length() { Some(CURSOR_PREFIX + show(end)) } else { None }33  Ok((items.slice(start, end), next))34}3536/// The offset a cursor names, when it is one this server issued.37fn offsetOf(cursor: Str, length: Int) -> Option[Int] {38  if !cursor.startsWith(CURSOR_PREFIX) { return None }39  let offset = Text.countOf(cursor.drop(CURSOR_PREFIX.length())) ?40  if offset < length { Some(offset) } else { None }41}42