Files
domogeek/vendor/github.com/yosida95/uritemplate/v3/escape.go
T
cyrilixandClaude Sonnet 5 e5468ef654 feat: add MCP endpoint exposing calendar tools over Streamable HTTP
Adds a POST /mcp endpoint (github.com/modelcontextprotocol/go-sdk) with
three tools mirroring the existing /calendar logic: get_calendar_today,
get_calendar_for_date and get_holidays. Bumps go.mod to Go 1.25 (required
by the SDK) and vendors the new dependencies. Also fixes an unanchored
.gitignore rule ("domogeek") that was silently excluding all untracked
files under cmd/domogeek/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hu8wwahgecuCGfesTKCfEd
2026-09-05 10:53:31 +02:00

191 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of The BSD 3-Clause License
// that can be found in the LICENSE file.
package uritemplate
import (
"strings"
"unicode"
"unicode/utf8"
)
var (
hex = []byte("0123456789ABCDEF")
// reserved = gen-delims / sub-delims
// gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
// sub-delims = "!" / "$" / "&" / "" / "(" / ")"
// / "*" / "+" / "," / ";" / "="
rangeReserved = &unicode.RangeTable{
R16: []unicode.Range16{
{Lo: 0x21, Hi: 0x21, Stride: 1}, // '!'
{Lo: 0x23, Hi: 0x24, Stride: 1}, // '#' - '$'
{Lo: 0x26, Hi: 0x2C, Stride: 1}, // '&' - ','
{Lo: 0x2F, Hi: 0x2F, Stride: 1}, // '/'
{Lo: 0x3A, Hi: 0x3B, Stride: 1}, // ':' - ';'
{Lo: 0x3D, Hi: 0x3D, Stride: 1}, // '='
{Lo: 0x3F, Hi: 0x40, Stride: 1}, // '?' - '@'
{Lo: 0x5B, Hi: 0x5B, Stride: 1}, // '['
{Lo: 0x5D, Hi: 0x5D, Stride: 1}, // ']'
},
LatinOffset: 9,
}
reReserved = `\x21\x23\x24\x26-\x2c\x2f\x3a\x3b\x3d\x3f\x40\x5b\x5d`
// ALPHA = %x41-5A / %x61-7A
// DIGIT = %x30-39
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
rangeUnreserved = &unicode.RangeTable{
R16: []unicode.Range16{
{Lo: 0x2D, Hi: 0x2E, Stride: 1}, // '-' - '.'
{Lo: 0x30, Hi: 0x39, Stride: 1}, // '0' - '9'
{Lo: 0x41, Hi: 0x5A, Stride: 1}, // 'A' - 'Z'
{Lo: 0x5F, Hi: 0x5F, Stride: 1}, // '_'
{Lo: 0x61, Hi: 0x7A, Stride: 1}, // 'a' - 'z'
{Lo: 0x7E, Hi: 0x7E, Stride: 1}, // '~'
},
}
reUnreserved = `\x2d\x2e\x30-\x39\x41-\x5a\x5f\x61-\x7a\x7e`
)
type runeClass uint8
const (
runeClassU runeClass = 1 << iota
runeClassR
runeClassPctE
runeClassLast
runeClassUR = runeClassU | runeClassR
)
var runeClassNames = []string{
"U",
"R",
"pct-encoded",
}
func (rc runeClass) String() string {
ret := make([]string, 0, len(runeClassNames))
for i, j := 0, runeClass(1); j < runeClassLast; j <<= 1 {
if rc&j == j {
ret = append(ret, runeClassNames[i])
}
i++
}
return strings.Join(ret, "+")
}
func pctEncode(w *strings.Builder, r rune) {
if s := r >> 24 & 0xff; s > 0 {
w.Write([]byte{'%', hex[s/16], hex[s%16]})
}
if s := r >> 16 & 0xff; s > 0 {
w.Write([]byte{'%', hex[s/16], hex[s%16]})
}
if s := r >> 8 & 0xff; s > 0 {
w.Write([]byte{'%', hex[s/16], hex[s%16]})
}
if s := r & 0xff; s > 0 {
w.Write([]byte{'%', hex[s/16], hex[s%16]})
}
}
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
func ishex(c byte) bool {
switch {
case '0' <= c && c <= '9':
return true
case 'a' <= c && c <= 'f':
return true
case 'A' <= c && c <= 'F':
return true
default:
return false
}
}
func pctDecode(s string) string {
size := len(s)
for i := 0; i < len(s); {
switch s[i] {
case '%':
size -= 2
i += 3
default:
i++
}
}
if size == len(s) {
return s
}
buf := make([]byte, size)
j := 0
for i := 0; i < len(s); {
switch c := s[i]; c {
case '%':
buf[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
i += 3
j++
default:
buf[j] = c
i++
j++
}
}
return string(buf)
}
type escapeFunc func(*strings.Builder, string) error
func escapeLiteral(w *strings.Builder, v string) error {
w.WriteString(v)
return nil
}
func escapeExceptU(w *strings.Builder, v string) error {
for i := 0; i < len(v); {
r, size := utf8.DecodeRuneInString(v[i:])
if r == utf8.RuneError {
return errorf(i, "invalid encoding")
}
if unicode.Is(rangeUnreserved, r) {
w.WriteRune(r)
} else {
pctEncode(w, r)
}
i += size
}
return nil
}
func escapeExceptUR(w *strings.Builder, v string) error {
for i := 0; i < len(v); {
r, size := utf8.DecodeRuneInString(v[i:])
if r == utf8.RuneError {
return errorf(i, "invalid encoding")
}
// TODO(yosida95): is pct-encoded triplets allowed here?
if unicode.In(r, rangeUnreserved, rangeReserved) {
w.WriteRune(r)
} else {
pctEncode(w, r)
}
i += size
}
return nil
}