Merge pull request 'feat/staff-crud-added' (#268) from feat/staff-crud-added into develop

Reviewed-on: ebhomengo/niki#268
Reviewed-by: hossein <h.nazari1990@gmail.com>
This commit is contained in:
hossein 2026-04-08 06:20:55 +00:00
commit 4fa7d7f10d
56 changed files with 9563 additions and 45632 deletions

View File

@ -1,15 +1,143 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"strconv"
"git.gocasts.ir/ebhomengo/niki/staffapp/repository/database"
"git.gocasts.ir/ebhomengo/niki/staffapp/service"
) )
func main() { func main() {
fmt.Println(" Staffapp Server Starting...")
staffDb := database.New()
staffService := service.NewStaffService(staffDb)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Staffapp OK!") fmt.Fprintf(w, "Staffapp OK!")
}) })
http.HandleFunc("/staff", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var newStaff service.Staff
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&newStaff)
if err != nil {
http.Error(w, "Invalid request payload: "+err.Error(), http.StatusBadRequest)
return
}
defer r.Body.Close()
createdStaff, err := staffService.RegisterStaff(newStaff.Name, newStaff.LastName, newStaff.PhoneNumber)
if err != nil {
http.Error(w, "Failed to register staff: "+err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(createdStaff)
})
http.HandleFunc("/staff/", func(w http.ResponseWriter, r *http.Request) {
idStr := r.URL.Path[len("/staff/"):]
if idStr == "" {
http.Error(w, "Missing staff ID", http.StatusBadRequest)
return
}
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "Invalid staff ID format", http.StatusBadRequest)
return
}
switch r.Method {
case http.MethodGet:
st, err := staffService.Get(id)
if err != nil {
if err.Error() == "staff not found" {
http.Error(w, "Staff not found", http.StatusNotFound)
} else {
http.Error(w, "Failed to fetch staff: "+err.Error(), http.StatusInternalServerError)
}
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(st)
case http.MethodPut:
var staffData struct {
Name string `json:"Name"`
LastName string `json:"LastName"`
PhoneNumber string `json:"PhoneNumber"`
}
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&staffData); err != nil {
http.Error(w, "Invalid request payload: "+err.Error(), http.StatusBadRequest)
return
}
defer r.Body.Close()
updatedStaff, err := staffService.Update(id, staffData.Name, staffData.LastName, staffData.PhoneNumber)
if err != nil {
if err.Error() == "staff not found" {
http.Error(w, "Staff not found", http.StatusNotFound)
} else {
http.Error(w, "Failed to update staff: "+err.Error(), http.StatusInternalServerError)
}
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(updatedStaff)
case http.MethodDelete:
err = staffService.Remove(id)
if err != nil {
if err.Error() == "staff not found" {
http.Error(w, "Staff not found", http.StatusNotFound)
} else {
http.Error(w, "Failed to remove staff: "+err.Error(), http.StatusInternalServerError)
}
return
}
w.WriteHeader(http.StatusNoContent)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
http.HandleFunc("/staffs", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
list, err := staffService.List()
if err != nil {
http.Error(w, "Failed to fetch staff list: "+err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(list)
})
log.Fatal(http.ListenAndServe(":8080", nil)) log.Fatal(http.ListenAndServe(":8080", nil))
} }

14
go.mod
View File

@ -18,7 +18,7 @@ require (
github.com/stretchr/testify v1.11.1 github.com/stretchr/testify v1.11.1
github.com/swaggo/echo-swagger v1.5.2 github.com/swaggo/echo-swagger v1.5.2
github.com/swaggo/swag v1.16.6 github.com/swaggo/swag v1.16.6
golang.org/x/crypto v0.46.0 golang.org/x/crypto v0.48.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/natefinch/lumberjack.v2 v2.2.1
) )
@ -77,13 +77,13 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
golang.org/x/mod v0.30.0 // indirect golang.org/x/mod v0.33.0 // indirect
golang.org/x/net v0.48.0 // indirect golang.org/x/net v0.50.0 // indirect
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.39.0 // indirect golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.32.0 // indirect golang.org/x/text v0.35.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.39.0 // indirect golang.org/x/tools v0.42.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect

28
go.sum
View File

@ -404,8 +404,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -415,8 +415,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -434,8 +434,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -448,8 +448,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -483,8 +483,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -492,8 +492,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
@ -508,8 +508,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1,15 +0,0 @@
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
fmt.Println(" Staffapp Server Starting...")
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Staffapp OK!")
})
log.Fatal(http.ListenAndServe(":8080", nil))
}

View File

@ -1,13 +1,64 @@
package database package database
import "git.gocasts.ir/ebhomengo/niki/repository/mysql" import (
"fmt"
"git.gocasts.ir/ebhomengo/niki/staffapp/service"
)
type DB struct { type DB struct {
conn *mysql.DB staffs []service.Staff
nextID int
} }
func New(conn *mysql.DB) *DB { func New() service.StaffRepository {
return &DB{ return &DB{
conn: conn, staffs: []service.Staff{},
nextID: 1,
} }
} }
func (d *DB) Create(staff service.Staff) (service.Staff, error) {
staff.ID = d.nextID
d.staffs = append(d.staffs, staff)
d.nextID++
return staff, nil
}
func (d *DB) Get(id int) (*service.Staff, error) {
for _, v := range d.staffs {
if id == v.ID {
return &v, nil
}
}
return nil, fmt.Errorf("The user not found with id = %d", id)
}
func (d *DB) List() ([]service.Staff, error) {
return d.staffs, nil
}
func (d *DB) Remove(id int) error {
for _, v := range d.staffs {
if id == v.ID {
d.staffs = append(d.staffs[:id], d.staffs[id+1:]...)
return nil
}
}
return fmt.Errorf("User with ID: %d notfound", id)
}
func (d *DB) Update(id int, name, lastName, phoneNumber string) (*service.Staff, error) {
for _, v := range d.staffs {
if id == v.ID {
v.Name = name
v.LastName = lastName
v.PhoneNumber = phoneNumber
return &v, nil
}
}
return nil, fmt.Errorf("User with this Id(%d)couldn't found for updating", id)
}

View File

@ -1 +0,0 @@
package service

View File

@ -1 +0,0 @@
package service

View File

@ -0,0 +1,15 @@
package service
type Staff struct {
ID int
Name string
LastName string
PhoneNumber string
}
type StaffRepository interface {
Create(staff Staff) (Staff, error)
Get(id int) (*Staff, error)
List() ([]Staff, error)
Remove(id int) error
Update(id int, name, lastName, phoneNumber string) (*Staff, error)
}

View File

@ -1 +1,44 @@
package service package service
import (
"fmt"
)
type StaffService struct {
repo StaffRepository
}
func NewStaffService(repo StaffRepository) *StaffService {
return &StaffService{
repo: repo,
}
}
func (s *StaffService) RegisterStaff(name, lastname, phone string) (Staff, error) {
newStaff := Staff{
Name: name,
LastName: lastname,
PhoneNumber: phone,
}
createdStaff, err := s.repo.Create(newStaff)
if err != nil {
return Staff{}, fmt.Errorf("Error in registring staff%w", err)
}
return createdStaff, nil
}
func (s *StaffService) Get(id int) (*Staff, error) {
return s.repo.Get(id)
}
func (s *StaffService) List() ([]Staff, error) {
return s.repo.List()
}
func (s *StaffService) Remove(id int) error {
return s.repo.Remove(id)
}
func (s *StaffService) Update(id int, name, lastName, phoneNumber string) (*Staff, error) {
return s.repo.Update(id, name, lastName, phoneNumber)
}

View File

@ -1 +0,0 @@
package service

View File

@ -802,8 +802,8 @@ func MatchPrefixPatterns(globs, target string) bool {
for globs != "" { for globs != "" {
// Extract next non-empty glob in comma-separated list. // Extract next non-empty glob in comma-separated list.
var glob string var glob string
if i := strings.Index(globs, ","); i >= 0 { if before, after, ok := strings.Cut(globs, ","); ok {
glob, globs = globs[:i], globs[i+1:] glob, globs = before, after
} else { } else {
glob, globs = globs, "" glob, globs = globs, ""
} }

20
vendor/golang.org/x/net/http2/client_priority_go126.go generated vendored Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.27
package http2
import "net/http"
// Support for go.dev/issue/75500 is added in Go 1.27. In case anyone uses
// x/net with versions before Go 1.27, we return true here so that their write
// scheduler will still be the round-robin write scheduler rather than the RFC
// 9218 write scheduler. That way, older users of Go will not see a sudden
// change of behavior just from importing x/net.
//
// TODO(nsh): remove this file after x/net go.mod is at Go 1.27.
func clientPriorityDisabled(_ *http.Server) bool {
return true
}

13
vendor/golang.org/x/net/http2/client_priority_go127.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.27
package http2
import "net/http"
func clientPriorityDisabled(s *http.Server) bool {
return s.DisableClientPriority
}

View File

@ -11,11 +11,13 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"slices"
"strings" "strings"
"sync" "sync"
"golang.org/x/net/http/httpguts" "golang.org/x/net/http/httpguts"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"golang.org/x/net/internal/httpsfv"
) )
const frameHeaderLen = 9 const frameHeaderLen = 9
@ -23,7 +25,8 @@ const frameHeaderLen = 9
var padZeros = make([]byte, 255) // zeros for padding var padZeros = make([]byte, 255) // zeros for padding
// A FrameType is a registered frame type as defined in // A FrameType is a registered frame type as defined in
// https://httpwg.org/specs/rfc7540.html#rfc.section.11.2 // https://httpwg.org/specs/rfc7540.html#rfc.section.11.2 and other future
// RFCs.
type FrameType uint8 type FrameType uint8
const ( const (
@ -37,6 +40,7 @@ const (
FrameGoAway FrameType = 0x7 FrameGoAway FrameType = 0x7
FrameWindowUpdate FrameType = 0x8 FrameWindowUpdate FrameType = 0x8
FrameContinuation FrameType = 0x9 FrameContinuation FrameType = 0x9
FramePriorityUpdate FrameType = 0x10
) )
var frameNames = [...]string{ var frameNames = [...]string{
@ -50,6 +54,7 @@ var frameNames = [...]string{
FrameGoAway: "GOAWAY", FrameGoAway: "GOAWAY",
FrameWindowUpdate: "WINDOW_UPDATE", FrameWindowUpdate: "WINDOW_UPDATE",
FrameContinuation: "CONTINUATION", FrameContinuation: "CONTINUATION",
FramePriorityUpdate: "PRIORITY_UPDATE",
} }
func (t FrameType) String() string { func (t FrameType) String() string {
@ -135,6 +140,7 @@ var frameParsers = [...]frameParser{
FrameGoAway: parseGoAwayFrame, FrameGoAway: parseGoAwayFrame,
FrameWindowUpdate: parseWindowUpdateFrame, FrameWindowUpdate: parseWindowUpdateFrame,
FrameContinuation: parseContinuationFrame, FrameContinuation: parseContinuationFrame,
FramePriorityUpdate: parsePriorityUpdateFrame,
} }
func typeFrameParser(t FrameType) frameParser { func typeFrameParser(t FrameType) frameParser {
@ -1180,9 +1186,34 @@ type PriorityFrame struct {
PriorityParam PriorityParam
} }
var defaultRFC9218Priority = PriorityParam{ // defaultRFC9218Priority determines what priority we should use as the default
incremental: 0, // value.
//
// According to RFC 9218, by default, streams should be given an urgency of 3
// and should be non-incremental. However, making streams non-incremental by
// default would be a huge change to our historical behavior where we would
// round-robin writes across streams. When streams are non-incremental, we
// would process streams of the same urgency one-by-one to completion instead.
//
// To avoid such a sudden change which might break some HTTP/2 users, this
// function allows the caller to specify whether they can actually use the
// default value as specified in RFC 9218. If not, this function will return a
// priority value where streams are incremental by default instead: effectively
// a round-robin between stream of the same urgency.
//
// As an example, a server might not be able to use the RFC 9218 default value
// when it's not sure that the client it is serving is aware of RFC 9218.
func defaultRFC9218Priority(canUseDefault bool) PriorityParam {
if canUseDefault {
return PriorityParam{
urgency: 3, urgency: 3,
incremental: 0,
}
}
return PriorityParam{
urgency: 3,
incremental: 1,
}
} }
// Note that HTTP/2 has had two different prioritization schemes, and // Note that HTTP/2 has had two different prioritization schemes, and
@ -1266,6 +1297,74 @@ func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
return f.endWrite() return f.endWrite()
} }
// PriorityUpdateFrame is a PRIORITY_UPDATE frame as described in
// https://www.rfc-editor.org/rfc/rfc9218.html#name-the-priority_update-frame.
type PriorityUpdateFrame struct {
FrameHeader
Priority string
PrioritizedStreamID uint32
}
func parseRFC9218Priority(s string, canUseDefault bool) (p PriorityParam, ok bool) {
p = defaultRFC9218Priority(canUseDefault)
ok = httpsfv.ParseDictionary(s, func(key, val, _ string) {
switch key {
case "u":
if u, ok := httpsfv.ParseInteger(val); ok && u >= 0 && u <= 7 {
p.urgency = uint8(u)
}
case "i":
if i, ok := httpsfv.ParseBoolean(val); ok {
if i {
p.incremental = 1
} else {
p.incremental = 0
}
}
}
})
if !ok {
return defaultRFC9218Priority(canUseDefault), ok
}
return p, true
}
func parsePriorityUpdateFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
if fh.StreamID != 0 {
countError("frame_priority_update_non_zero_stream")
return nil, connError{ErrCodeProtocol, "PRIORITY_UPDATE frame with non-zero stream ID"}
}
if len(payload) < 4 {
countError("frame_priority_update_bad_length")
return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY_UPDATE frame payload size was %d; want at least 4", len(payload))}
}
v := binary.BigEndian.Uint32(payload[:4])
streamID := v & 0x7fffffff // mask off high bit
if streamID == 0 {
countError("frame_priority_update_prioritizing_zero_stream")
return nil, connError{ErrCodeProtocol, "PRIORITY_UPDATE frame with prioritized stream ID of zero"}
}
return &PriorityUpdateFrame{
FrameHeader: fh,
PrioritizedStreamID: streamID,
Priority: string(payload[4:]),
}, nil
}
// WritePriorityUpdate writes a PRIORITY_UPDATE frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WritePriorityUpdate(streamID uint32, priority string) error {
if !validStreamID(streamID) && !f.AllowIllegalWrites {
return errStreamID
}
f.startWrite(FramePriorityUpdate, 0, 0)
f.writeUint32(streamID)
f.writeBytes([]byte(priority))
return f.endWrite()
}
// A RSTStreamFrame allows for abnormal termination of a stream. // A RSTStreamFrame allows for abnormal termination of a stream.
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.4 // See https://httpwg.org/specs/rfc7540.html#rfc.section.6.4
type RSTStreamFrame struct { type RSTStreamFrame struct {
@ -1547,6 +1646,23 @@ func (mh *MetaHeadersFrame) PseudoFields() []hpack.HeaderField {
return mh.Fields return mh.Fields
} }
func (mh *MetaHeadersFrame) rfc9218Priority(priorityAware bool) (p PriorityParam, priorityAwareAfter, hasIntermediary bool) {
var s string
for _, field := range mh.Fields {
if field.Name == "priority" {
s = field.Value
priorityAware = true
}
if slices.Contains([]string{"via", "forwarded", "x-forwarded-for"}, field.Name) {
hasIntermediary = true
}
}
// No need to check for ok. parseRFC9218Priority will return a default
// value if there is no priority field or if the field cannot be parsed.
p, _ = parseRFC9218Priority(s, priorityAware && !hasIntermediary)
return p, priorityAware, hasIntermediary
}
func (mh *MetaHeadersFrame) checkPseudos() error { func (mh *MetaHeadersFrame) checkPseudos() error {
var isRequest, isResponse bool var isRequest, isResponse bool
pf := mh.PseudoFields() pf := mh.PseudoFields()

View File

@ -169,6 +169,7 @@ const (
SettingMaxFrameSize SettingID = 0x5 SettingMaxFrameSize SettingID = 0x5
SettingMaxHeaderListSize SettingID = 0x6 SettingMaxHeaderListSize SettingID = 0x6
SettingEnableConnectProtocol SettingID = 0x8 SettingEnableConnectProtocol SettingID = 0x8
SettingNoRFC7540Priorities SettingID = 0x9
) )
var settingName = map[SettingID]string{ var settingName = map[SettingID]string{
@ -179,6 +180,7 @@ var settingName = map[SettingID]string{
SettingMaxFrameSize: "MAX_FRAME_SIZE", SettingMaxFrameSize: "MAX_FRAME_SIZE",
SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE", SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL", SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL",
SettingNoRFC7540Priorities: "NO_RFC7540_PRIORITIES",
} }
func (s SettingID) String() string { func (s SettingID) String() string {

View File

@ -472,10 +472,13 @@ func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverCon
sc.conn.SetWriteDeadline(time.Time{}) sc.conn.SetWriteDeadline(time.Time{})
} }
if s.NewWriteScheduler != nil { switch {
case s.NewWriteScheduler != nil:
sc.writeSched = s.NewWriteScheduler() sc.writeSched = s.NewWriteScheduler()
} else { case clientPriorityDisabled(http1srv):
sc.writeSched = newRoundRobinWriteScheduler() sc.writeSched = newRoundRobinWriteScheduler()
default:
sc.writeSched = newPriorityWriteSchedulerRFC9218()
} }
// These start at the RFC-specified defaults. If there is a higher // These start at the RFC-specified defaults. If there is a higher
@ -648,6 +651,23 @@ type serverConn struct {
// Used by startGracefulShutdown. // Used by startGracefulShutdown.
shutdownOnce sync.Once shutdownOnce sync.Once
// Used for RFC 9218 prioritization.
hasIntermediary bool // connection is done via an intermediary / proxy
priorityAware bool // the client has sent priority signal, meaning that it is aware of it.
}
func (sc *serverConn) writeSchedIgnoresRFC7540() bool {
switch sc.writeSched.(type) {
case *priorityWriteSchedulerRFC9218:
return true
case *randomWriteScheduler:
return true
case *roundRobinWriteScheduler:
return true
default:
return false
}
} }
func (sc *serverConn) maxHeaderListSize() uint32 { func (sc *serverConn) maxHeaderListSize() uint32 {
@ -938,6 +958,9 @@ func (sc *serverConn) serve(conf http2Config) {
if !disableExtendedConnectProtocol { if !disableExtendedConnectProtocol {
settings = append(settings, Setting{SettingEnableConnectProtocol, 1}) settings = append(settings, Setting{SettingEnableConnectProtocol, 1})
} }
if sc.writeSchedIgnoresRFC7540() {
settings = append(settings, Setting{SettingNoRFC7540Priorities, 1})
}
sc.writeFrame(FrameWriteRequest{ sc.writeFrame(FrameWriteRequest{
write: settings, write: settings,
}) })
@ -1623,6 +1646,8 @@ func (sc *serverConn) processFrame(f Frame) error {
// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR. // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
return sc.countError("push_promise", ConnectionError(ErrCodeProtocol)) return sc.countError("push_promise", ConnectionError(ErrCodeProtocol))
case *PriorityUpdateFrame:
return sc.processPriorityUpdate(f)
default: default:
sc.vlogf("http2: server ignoring frame: %v", f.Header()) sc.vlogf("http2: server ignoring frame: %v", f.Header())
return nil return nil
@ -1803,6 +1828,10 @@ func (sc *serverConn) processSetting(s Setting) error {
case SettingEnableConnectProtocol: case SettingEnableConnectProtocol:
// Receipt of this parameter by a server does not // Receipt of this parameter by a server does not
// have any impact // have any impact
case SettingNoRFC7540Priorities:
if s.Val > 1 {
return ConnectionError(ErrCodeProtocol)
}
default: default:
// Unknown setting: "An endpoint that receives a SETTINGS // Unknown setting: "An endpoint that receives a SETTINGS
// frame with any unknown or unsupported identifier MUST // frame with any unknown or unsupported identifier MUST
@ -2073,14 +2102,34 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
if f.StreamEnded() { if f.StreamEnded() {
initialState = stateHalfClosedRemote initialState = stateHalfClosedRemote
} }
st := sc.newStream(id, 0, initialState)
// We are handling two special cases here:
// 1. When a request is sent via an intermediary, we force priority to be
// u=3,i. This is essentially a round-robin behavior, and is done to ensure
// fairness between, for example, multiple clients using the same proxy.
// 2. Until a client has shown that it is aware of RFC 9218, we make its
// streams non-incremental by default. This is done to preserve the
// historical behavior of handling streams in a round-robin manner, rather
// than one-by-one to completion.
initialPriority := defaultRFC9218Priority(sc.priorityAware && !sc.hasIntermediary)
if _, ok := sc.writeSched.(*priorityWriteSchedulerRFC9218); ok && !sc.hasIntermediary {
headerPriority, priorityAware, hasIntermediary := f.rfc9218Priority(sc.priorityAware)
initialPriority = headerPriority
sc.hasIntermediary = hasIntermediary
if priorityAware {
sc.priorityAware = true
}
}
st := sc.newStream(id, 0, initialState, initialPriority)
if f.HasPriority() { if f.HasPriority() {
if err := sc.checkPriority(f.StreamID, f.Priority); err != nil { if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {
return err return err
} }
if !sc.writeSchedIgnoresRFC7540() {
sc.writeSched.AdjustStream(st.id, f.Priority) sc.writeSched.AdjustStream(st.id, f.Priority)
} }
}
rw, req, err := sc.newWriterAndRequest(st, f) rw, req, err := sc.newWriterAndRequest(st, f)
if err != nil { if err != nil {
@ -2120,7 +2169,7 @@ func (sc *serverConn) upgradeRequest(req *http.Request) {
sc.serveG.check() sc.serveG.check()
id := uint32(1) id := uint32(1)
sc.maxClientStreamID = id sc.maxClientStreamID = id
st := sc.newStream(id, 0, stateHalfClosedRemote) st := sc.newStream(id, 0, stateHalfClosedRemote, defaultRFC9218Priority(sc.priorityAware && !sc.hasIntermediary))
st.reqTrailer = req.Trailer st.reqTrailer = req.Trailer
if st.reqTrailer != nil { if st.reqTrailer != nil {
st.trailer = make(http.Header) st.trailer = make(http.Header)
@ -2185,11 +2234,32 @@ func (sc *serverConn) processPriority(f *PriorityFrame) error {
if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil { if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
return err return err
} }
// We need to avoid calling AdjustStream when using the RFC 9218 write
// scheduler. Otherwise, incremental's zero value in PriorityParam will
// unexpectedly make all streams non-incremental. This causes us to process
// streams one-by-one to completion rather than doing it in a round-robin
// manner (the historical behavior), which might be unexpected to users.
if sc.writeSchedIgnoresRFC7540() {
return nil
}
sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam) sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
return nil return nil
} }
func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream { func (sc *serverConn) processPriorityUpdate(f *PriorityUpdateFrame) error {
sc.priorityAware = true
if _, ok := sc.writeSched.(*priorityWriteSchedulerRFC9218); !ok {
return nil
}
p, ok := parseRFC9218Priority(f.Priority, sc.priorityAware)
if !ok {
return sc.countError("unparsable_priority_update", streamError(f.PrioritizedStreamID, ErrCodeProtocol))
}
sc.writeSched.AdjustStream(f.PrioritizedStreamID, p)
return nil
}
func (sc *serverConn) newStream(id, pusherID uint32, state streamState, priority PriorityParam) *stream {
sc.serveG.check() sc.serveG.check()
if id == 0 { if id == 0 {
panic("internal error: cannot create stream with id 0") panic("internal error: cannot create stream with id 0")
@ -2212,7 +2282,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
} }
sc.streams[id] = st sc.streams[id] = st
sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID}) sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID, priority: priority})
if st.isPushed() { if st.isPushed() {
sc.curPushedStreams++ sc.curPushedStreams++
} else { } else {
@ -3218,7 +3288,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
// transition to "half closed (remote)" after sending the initial HEADERS, but // transition to "half closed (remote)" after sending the initial HEADERS, but
// we start in "half closed (remote)" for simplicity. // we start in "half closed (remote)" for simplicity.
// See further comments at the definition of stateHalfClosedRemote. // See further comments at the definition of stateHalfClosedRemote.
promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote) promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote, defaultRFC9218Priority(sc.priorityAware && !sc.hasIntermediary))
rw, req, err := sc.newWriterAndRequestNoBody(promised, httpcommon.ServerRequestParam{ rw, req, err := sc.newWriterAndRequestNoBody(promised, httpcommon.ServerRequestParam{
Method: msg.method, Method: msg.method,
Scheme: msg.url.Scheme, Scheme: msg.url.Scheme,

View File

@ -2779,6 +2779,11 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
cs.abortStream(err) cs.abortStream(err)
} }
func (rl *clientConnReadLoop) endStreamErrorLocked(cs *clientStream, err error) {
cs.readAborted = true
cs.abortStreamLocked(err)
}
// Constants passed to streamByID for documentation purposes. // Constants passed to streamByID for documentation purposes.
const ( const (
headerOrDataFrame = true headerOrDataFrame = true
@ -2946,7 +2951,7 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
if !fl.add(int32(f.Increment)) { if !fl.add(int32(f.Increment)) {
// For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR // For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR
if cs != nil { if cs != nil {
rl.endStreamError(cs, StreamError{ rl.endStreamErrorLocked(cs, StreamError{
StreamID: f.StreamID, StreamID: f.StreamID,
Code: ErrCodeFlowControl, Code: ErrCodeFlowControl,
}) })

View File

@ -56,6 +56,10 @@ type PriorityWriteSchedulerConfig struct {
// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3. // frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
// If cfg is nil, default options are used. // If cfg is nil, default options are used.
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler { func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
return newPriorityWriteSchedulerRFC7540(cfg)
}
func newPriorityWriteSchedulerRFC7540(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
if cfg == nil { if cfg == nil {
// For justification of these defaults, see: // For justification of these defaults, see:
// https://docs.google.com/document/d/1oLhNg1skaWD4_DtaoCxdSRN5erEXrH-KnLrMwEpOtFY // https://docs.google.com/document/d/1oLhNg1skaWD4_DtaoCxdSRN5erEXrH-KnLrMwEpOtFY

View File

@ -37,6 +37,15 @@ type priorityWriteSchedulerRFC9218 struct {
// incremental streams or not, when urgency is the same in a given Pop() // incremental streams or not, when urgency is the same in a given Pop()
// call. // call.
prioritizeIncremental bool prioritizeIncremental bool
// priorityUpdateBuf is used to buffer the most recent PRIORITY_UPDATE we
// receive per https://www.rfc-editor.org/rfc/rfc9218.html#name-the-priority_update-frame.
priorityUpdateBuf struct {
// streamID being 0 means that the buffer is empty. This is a safe
// assumption as PRIORITY_UPDATE for stream 0 is a PROTOCOL_ERROR.
streamID uint32
priority PriorityParam
}
} }
func newPriorityWriteSchedulerRFC9218() WriteScheduler { func newPriorityWriteSchedulerRFC9218() WriteScheduler {
@ -50,6 +59,10 @@ func (ws *priorityWriteSchedulerRFC9218) OpenStream(streamID uint32, opt OpenStr
if ws.streams[streamID].location != nil { if ws.streams[streamID].location != nil {
panic(fmt.Errorf("stream %d already opened", streamID)) panic(fmt.Errorf("stream %d already opened", streamID))
} }
if streamID == ws.priorityUpdateBuf.streamID {
ws.priorityUpdateBuf.streamID = 0
opt.priority = ws.priorityUpdateBuf.priority
}
q := ws.queuePool.get() q := ws.queuePool.get()
ws.streams[streamID] = streamMetadata{ ws.streams[streamID] = streamMetadata{
location: q, location: q,
@ -95,6 +108,8 @@ func (ws *priorityWriteSchedulerRFC9218) AdjustStream(streamID uint32, priority
metadata := ws.streams[streamID] metadata := ws.streams[streamID]
q, u, i := metadata.location, metadata.priority.urgency, metadata.priority.incremental q, u, i := metadata.location, metadata.priority.urgency, metadata.priority.incremental
if q == nil { if q == nil {
ws.priorityUpdateBuf.streamID = streamID
ws.priorityUpdateBuf.priority = priority
return return
} }

665
vendor/golang.org/x/net/internal/httpsfv/httpsfv.go generated vendored Normal file
View File

@ -0,0 +1,665 @@
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package httpsfv provides functionality for dealing with HTTP Structured
// Field Values.
package httpsfv
import (
"slices"
"strconv"
"strings"
"time"
"unicode/utf8"
)
func isLCAlpha(b byte) bool {
return (b >= 'a' && b <= 'z')
}
func isAlpha(b byte) bool {
return isLCAlpha(b) || (b >= 'A' && b <= 'Z')
}
func isDigit(b byte) bool {
return b >= '0' && b <= '9'
}
func isVChar(b byte) bool {
return b >= 0x21 && b <= 0x7e
}
func isSP(b byte) bool {
return b == 0x20
}
func isTChar(b byte) bool {
if isAlpha(b) || isDigit(b) {
return true
}
return slices.Contains([]byte{'!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~'}, b)
}
func countLeftWhitespace(s string) int {
i := 0
for _, ch := range []byte(s) {
if ch != ' ' && ch != '\t' {
break
}
i++
}
return i
}
// https://www.rfc-editor.org/rfc/rfc4648#section-8.
func decOctetHex(ch1, ch2 byte) (ch byte, ok bool) {
decBase16 := func(in byte) (out byte, ok bool) {
if !isDigit(in) && !(in >= 'a' && in <= 'f') {
return 0, false
}
if isDigit(in) {
return in - '0', true
}
return in - 'a' + 10, true
}
if ch1, ok = decBase16(ch1); !ok {
return 0, ok
}
if ch2, ok = decBase16(ch2); !ok {
return 0, ok
}
return ch1<<4 | ch2, true
}
// ParseList parses a list from a given HTTP Structured Field Values.
//
// Given an HTTP SFV string that represents a list, it will call the given
// function using each of the members and parameters contained in the list.
// This allows the caller to extract information out of the list.
//
// This function will return once it encounters the end of the string, or
// something that is not a list. If it cannot consume the entire given
// string, the ok value returned will be false.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-list.
func ParseList(s string, f func(member, param string)) (ok bool) {
for len(s) != 0 {
var member, param string
if len(s) != 0 && s[0] == '(' {
if member, s, ok = consumeBareInnerList(s, nil); !ok {
return ok
}
} else {
if member, s, ok = consumeBareItem(s); !ok {
return ok
}
}
if param, s, ok = consumeParameter(s, nil); !ok {
return ok
}
if f != nil {
f(member, param)
}
s = s[countLeftWhitespace(s):]
if len(s) == 0 {
break
}
if s[0] != ',' {
return false
}
s = s[1:]
s = s[countLeftWhitespace(s):]
if len(s) == 0 {
return false
}
}
return true
}
// consumeBareInnerList consumes an inner list
// (https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-inner-list),
// except for the inner list's top-most parameter.
// For example, given `(a;b c;d);e`, it will consume only `(a;b c;d)`.
func consumeBareInnerList(s string, f func(bareItem, param string)) (consumed, rest string, ok bool) {
if len(s) == 0 || s[0] != '(' {
return "", s, false
}
rest = s[1:]
for len(rest) != 0 {
var bareItem, param string
rest = rest[countLeftWhitespace(rest):]
if len(rest) != 0 && rest[0] == ')' {
rest = rest[1:]
break
}
if bareItem, rest, ok = consumeBareItem(rest); !ok {
return "", s, ok
}
if param, rest, ok = consumeParameter(rest, nil); !ok {
return "", s, ok
}
if len(rest) == 0 || (rest[0] != ')' && !isSP(rest[0])) {
return "", s, false
}
if f != nil {
f(bareItem, param)
}
}
return s[:len(s)-len(rest)], rest, true
}
// ParseBareInnerList parses a bare inner list from a given HTTP Structured
// Field Values.
//
// We define a bare inner list as an inner list
// (https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-inner-list),
// without the top-most parameter of the inner list. For example, given the
// inner list `(a;b c;d);e`, the bare inner list would be `(a;b c;d)`.
//
// Given an HTTP SFV string that represents a bare inner list, it will call the
// given function using each of the bare item and parameter within the bare
// inner list. This allows the caller to extract information out of the bare
// inner list.
//
// This function will return once it encounters the end of the bare inner list,
// or something that is not a bare inner list. If it cannot consume the entire
// given string, the ok value returned will be false.
func ParseBareInnerList(s string, f func(bareItem, param string)) (ok bool) {
_, rest, ok := consumeBareInnerList(s, f)
return rest == "" && ok
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-item.
func consumeItem(s string, f func(bareItem, param string)) (consumed, rest string, ok bool) {
var bareItem, param string
if bareItem, rest, ok = consumeBareItem(s); !ok {
return "", s, ok
}
if param, rest, ok = consumeParameter(rest, nil); !ok {
return "", s, ok
}
if f != nil {
f(bareItem, param)
}
return s[:len(s)-len(rest)], rest, true
}
// ParseItem parses an item from a given HTTP Structured Field Values.
//
// Given an HTTP SFV string that represents an item, it will call the given
// function once, with the bare item and the parameter of the item. This allows
// the caller to extract information out of the item.
//
// This function will return once it encounters the end of the string, or
// something that is not an item. If it cannot consume the entire given
// string, the ok value returned will be false.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-item.
func ParseItem(s string, f func(bareItem, param string)) (ok bool) {
_, rest, ok := consumeItem(s, f)
return rest == "" && ok
}
// ParseDictionary parses a dictionary from a given HTTP Structured Field
// Values.
//
// Given an HTTP SFV string that represents a dictionary, it will call the
// given function using each of the keys, values, and parameters contained in
// the dictionary. This allows the caller to extract information out of the
// dictionary.
//
// This function will return once it encounters the end of the string, or
// something that is not a dictionary. If it cannot consume the entire given
// string, the ok value returned will be false.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-dictionary.
func ParseDictionary(s string, f func(key, val, param string)) (ok bool) {
for len(s) != 0 {
var key, val, param string
val = "?1" // Default value for empty val is boolean true.
if key, s, ok = consumeKey(s); !ok {
return ok
}
if len(s) != 0 && s[0] == '=' {
s = s[1:]
if len(s) != 0 && s[0] == '(' {
if val, s, ok = consumeBareInnerList(s, nil); !ok {
return ok
}
} else {
if val, s, ok = consumeBareItem(s); !ok {
return ok
}
}
}
if param, s, ok = consumeParameter(s, nil); !ok {
return ok
}
if f != nil {
f(key, val, param)
}
s = s[countLeftWhitespace(s):]
if len(s) == 0 {
break
}
if s[0] == ',' {
s = s[1:]
}
s = s[countLeftWhitespace(s):]
if len(s) == 0 {
return false
}
}
return true
}
// https://www.rfc-editor.org/rfc/rfc9651.html#parse-param.
func consumeParameter(s string, f func(key, val string)) (consumed, rest string, ok bool) {
rest = s
for len(rest) != 0 {
var key, val string
val = "?1" // Default value for empty val is boolean true.
if rest[0] != ';' {
break
}
rest = rest[1:]
rest = rest[countLeftWhitespace(rest):]
key, rest, ok = consumeKey(rest)
if !ok {
return "", s, ok
}
if len(rest) != 0 && rest[0] == '=' {
rest = rest[1:]
val, rest, ok = consumeBareItem(rest)
if !ok {
return "", s, ok
}
}
if f != nil {
f(key, val)
}
}
return s[:len(s)-len(rest)], rest, true
}
// ParseParameter parses a parameter from a given HTTP Structured Field Values.
//
// Given an HTTP SFV string that represents a parameter, it will call the given
// function using each of the keys and values contained in the parameter. This
// allows the caller to extract information out of the parameter.
//
// This function will return once it encounters the end of the string, or
// something that is not a parameter. If it cannot consume the entire given
// string, the ok value returned will be false.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#parse-param.
func ParseParameter(s string, f func(key, val string)) (ok bool) {
_, rest, ok := consumeParameter(s, f)
return rest == "" && ok
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-key.
func consumeKey(s string) (consumed, rest string, ok bool) {
if len(s) == 0 || (!isLCAlpha(s[0]) && s[0] != '*') {
return "", s, false
}
i := 0
for _, ch := range []byte(s) {
if !isLCAlpha(ch) && !isDigit(ch) && !slices.Contains([]byte("_-.*"), ch) {
break
}
i++
}
return s[:i], s[i:], true
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-integer-or-decim.
func consumeIntegerOrDecimal(s string) (consumed, rest string, ok bool) {
var i, signOffset, periodIndex int
var isDecimal bool
if i < len(s) && s[i] == '-' {
i++
signOffset++
}
if i >= len(s) {
return "", s, false
}
if !isDigit(s[i]) {
return "", s, false
}
for i < len(s) {
ch := s[i]
if isDigit(ch) {
i++
continue
}
if !isDecimal && ch == '.' {
if i-signOffset > 12 {
return "", s, false
}
periodIndex = i
isDecimal = true
i++
continue
}
break
}
if !isDecimal && i-signOffset > 15 {
return "", s, false
}
if isDecimal {
if i-signOffset > 16 {
return "", s, false
}
if s[i-1] == '.' {
return "", s, false
}
if i-periodIndex-1 > 3 {
return "", s, false
}
}
return s[:i], s[i:], true
}
// ParseInteger parses an integer from a given HTTP Structured Field Values.
//
// The entire HTTP SFV string must consist of a valid integer. It returns the
// parsed integer and an ok boolean value, indicating success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-integer-or-decim.
func ParseInteger(s string) (parsed int64, ok bool) {
if _, rest, ok := consumeIntegerOrDecimal(s); !ok || rest != "" {
return 0, false
}
if n, err := strconv.ParseInt(s, 10, 64); err == nil {
return n, true
}
return 0, false
}
// ParseDecimal parses a decimal from a given HTTP Structured Field Values.
//
// The entire HTTP SFV string must consist of a valid decimal. It returns the
// parsed decimal and an ok boolean value, indicating success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-an-integer-or-decim.
func ParseDecimal(s string) (parsed float64, ok bool) {
if _, rest, ok := consumeIntegerOrDecimal(s); !ok || rest != "" {
return 0, false
}
if !strings.Contains(s, ".") {
return 0, false
}
if n, err := strconv.ParseFloat(s, 64); err == nil {
return n, true
}
return 0, false
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-string.
func consumeString(s string) (consumed, rest string, ok bool) {
if len(s) == 0 || s[0] != '"' {
return "", s, false
}
for i := 1; i < len(s); i++ {
switch ch := s[i]; ch {
case '\\':
if i+1 >= len(s) {
return "", s, false
}
i++
if ch = s[i]; ch != '"' && ch != '\\' {
return "", s, false
}
case '"':
return s[:i+1], s[i+1:], true
default:
if !isVChar(ch) && !isSP(ch) {
return "", s, false
}
}
}
return "", s, false
}
// ParseString parses a Go string from a given HTTP Structured Field Values.
//
// The entire HTTP SFV string must consist of a valid string. It returns the
// parsed string and an ok boolean value, indicating success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-string.
func ParseString(s string) (parsed string, ok bool) {
if _, rest, ok := consumeString(s); !ok || rest != "" {
return "", false
}
return s[1 : len(s)-1], true
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-token
func consumeToken(s string) (consumed, rest string, ok bool) {
if len(s) == 0 || (!isAlpha(s[0]) && s[0] != '*') {
return "", s, false
}
i := 0
for _, ch := range []byte(s) {
if !isTChar(ch) && !slices.Contains([]byte(":/"), ch) {
break
}
i++
}
return s[:i], s[i:], true
}
// ParseToken parses a token from a given HTTP Structured Field Values.
//
// The entire HTTP SFV string must consist of a valid token. It returns the
// parsed token and an ok boolean value, indicating success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-token
func ParseToken(s string) (parsed string, ok bool) {
if _, rest, ok := consumeToken(s); !ok || rest != "" {
return "", false
}
return s, true
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-byte-sequence.
func consumeByteSequence(s string) (consumed, rest string, ok bool) {
if len(s) == 0 || s[0] != ':' {
return "", s, false
}
for i := 1; i < len(s); i++ {
if ch := s[i]; ch == ':' {
return s[:i+1], s[i+1:], true
}
if ch := s[i]; !isAlpha(ch) && !isDigit(ch) && !slices.Contains([]byte("+/="), ch) {
return "", s, false
}
}
return "", s, false
}
// ParseByteSequence parses a byte sequence from a given HTTP Structured Field
// Values.
//
// The entire HTTP SFV string must consist of a valid byte sequence. It returns
// the parsed byte sequence and an ok boolean value, indicating success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-byte-sequence.
func ParseByteSequence(s string) (parsed []byte, ok bool) {
if _, rest, ok := consumeByteSequence(s); !ok || rest != "" {
return nil, false
}
return []byte(s[1 : len(s)-1]), true
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-boolean.
func consumeBoolean(s string) (consumed, rest string, ok bool) {
if len(s) >= 2 && (s[:2] == "?0" || s[:2] == "?1") {
return s[:2], s[2:], true
}
return "", s, false
}
// ParseBoolean parses a boolean from a given HTTP Structured Field Values.
//
// The entire HTTP SFV string must consist of a valid boolean. It returns the
// parsed boolean and an ok boolean value, indicating success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-boolean.
func ParseBoolean(s string) (parsed bool, ok bool) {
if _, rest, ok := consumeBoolean(s); !ok || rest != "" {
return false, false
}
return s == "?1", true
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-date.
func consumeDate(s string) (consumed, rest string, ok bool) {
if len(s) == 0 || s[0] != '@' {
return "", s, false
}
if _, rest, ok = consumeIntegerOrDecimal(s[1:]); !ok {
return "", s, ok
}
consumed = s[:len(s)-len(rest)]
if slices.Contains([]byte(consumed), '.') {
return "", s, false
}
return consumed, rest, ok
}
// ParseDate parses a date from a given HTTP Structured Field Values.
//
// The entire HTTP SFV string must consist of a valid date. It returns the
// parsed date and an ok boolean value, indicating success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-date.
func ParseDate(s string) (parsed time.Time, ok bool) {
if _, rest, ok := consumeDate(s); !ok || rest != "" {
return time.Time{}, false
}
if n, ok := ParseInteger(s[1:]); !ok {
return time.Time{}, false
} else {
return time.Unix(n, 0), true
}
}
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-display-string.
func consumeDisplayString(s string) (consumed, rest string, ok bool) {
// To prevent excessive allocation, especially when input is large, we
// maintain a buffer of 4 bytes to keep track of the last rune we
// encounter. This way, we can validate that the display string conforms to
// UTF-8 without actually building the whole string.
var lastRune [4]byte
var runeLen int
isPartOfValidRune := func(ch byte) bool {
lastRune[runeLen] = ch
runeLen++
if utf8.FullRune(lastRune[:runeLen]) {
r, s := utf8.DecodeRune(lastRune[:runeLen])
if r == utf8.RuneError {
return false
}
copy(lastRune[:], lastRune[s:runeLen])
runeLen -= s
return true
}
return runeLen <= 4
}
if len(s) <= 1 || s[:2] != `%"` {
return "", s, false
}
i := 2
for i < len(s) {
ch := s[i]
if !isVChar(ch) && !isSP(ch) {
return "", s, false
}
switch ch {
case '"':
if runeLen > 0 {
return "", s, false
}
return s[:i+1], s[i+1:], true
case '%':
if i+2 >= len(s) {
return "", s, false
}
if ch, ok = decOctetHex(s[i+1], s[i+2]); !ok {
return "", s, ok
}
if ok = isPartOfValidRune(ch); !ok {
return "", s, ok
}
i += 3
default:
if ok = isPartOfValidRune(ch); !ok {
return "", s, ok
}
i++
}
}
return "", s, false
}
// ParseDisplayString parses a display string from a given HTTP Structured
// Field Values.
//
// The entire HTTP SFV string must consist of a valid display string. It
// returns the parsed display string and an ok boolean value, indicating
// success or not.
//
// https://www.rfc-editor.org/rfc/rfc9651.html#name-parsing-a-display-string.
func ParseDisplayString(s string) (parsed string, ok bool) {
if _, rest, ok := consumeDisplayString(s); !ok || rest != "" {
return "", false
}
// consumeDisplayString() already validates that we have a valid display
// string. Therefore, we can just construct the display string, without
// validating it again.
s = s[2 : len(s)-1]
var b strings.Builder
for i := 0; i < len(s); {
if s[i] == '%' {
decoded, _ := decOctetHex(s[i+1], s[i+2])
b.WriteByte(decoded)
i += 3
continue
}
b.WriteByte(s[i])
i++
}
return b.String(), true
}
// https://www.rfc-editor.org/rfc/rfc9651.html#parse-bare-item.
func consumeBareItem(s string) (consumed, rest string, ok bool) {
if len(s) == 0 {
return "", s, false
}
ch := s[0]
switch {
case ch == '-' || isDigit(ch):
return consumeIntegerOrDecimal(s)
case ch == '"':
return consumeString(s)
case ch == '*' || isAlpha(ch):
return consumeToken(s)
case ch == ':':
return consumeByteSequence(s)
case ch == '?':
return consumeBoolean(s)
case ch == '@':
return consumeDate(s)
case ch == '%':
return consumeDisplayString(s)
default:
return "", s, false
}
}

View File

@ -6,9 +6,7 @@
package unix package unix
import ( import "unsafe"
"unsafe"
)
// ioctl itself should not be exposed directly, but additional get/set // ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible. // functions for specific types are permissible.
@ -28,6 +26,13 @@ func IoctlSetPointerInt(fd int, req int, value int) error {
return ioctlPtr(fd, req, unsafe.Pointer(&v)) return ioctlPtr(fd, req, unsafe.Pointer(&v))
} }
// IoctlSetString performs an ioctl operation which sets a string value
// on fd, using the specified request number.
func IoctlSetString(fd int, req int, value string) error {
bs := append([]byte(value), 0)
return ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
// //
// To change fd's window size, the req argument should be TIOCSWINSZ. // To change fd's window size, the req argument should be TIOCSWINSZ.

View File

@ -6,9 +6,7 @@
package unix package unix
import ( import "unsafe"
"unsafe"
)
// ioctl itself should not be exposed directly, but additional get/set // ioctl itself should not be exposed directly, but additional get/set
// functions for specific types are permissible. // functions for specific types are permissible.
@ -28,6 +26,13 @@ func IoctlSetPointerInt(fd int, req uint, value int) error {
return ioctlPtr(fd, req, unsafe.Pointer(&v)) return ioctlPtr(fd, req, unsafe.Pointer(&v))
} }
// IoctlSetString performs an ioctl operation which sets a string value
// on fd, using the specified request number.
func IoctlSetString(fd int, req uint, value string) error {
bs := append([]byte(value), 0)
return ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
}
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument. // IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
// //
// To change fd's window size, the req argument should be TIOCSWINSZ. // To change fd's window size, the req argument should be TIOCSWINSZ.

View File

@ -1052,14 +1052,6 @@ func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
return ioctlRet(fd, req, uintptr(arg)) return ioctlRet(fd, req, uintptr(arg))
} }
func IoctlSetString(fd int, req int, val string) error {
bs := make([]byte, len(val)+1)
copy(bs[:len(bs)-1], val)
err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
runtime.KeepAlive(&bs[0])
return err
}
// Lifreq Helpers // Lifreq Helpers
func (l *Lifreq) SetName(name string) error { func (l *Lifreq) SetName(name string) error {

View File

@ -367,7 +367,9 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from
iov[0].SetLen(len(p)) iov[0].SetLen(len(p))
} }
var rsa RawSockaddrAny var rsa RawSockaddrAny
n, oobn, recvflags, err = recvmsgRaw(fd, iov[:], oob, flags, &rsa) if n, oobn, recvflags, err = recvmsgRaw(fd, iov[:], oob, flags, &rsa); err != nil {
return
}
// source address is only specified if the socket is unconnected // source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC { if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(fd, &rsa) from, err = anyToSockaddr(fd, &rsa)
@ -389,8 +391,10 @@ func RecvmsgBuffers(fd int, buffers [][]byte, oob []byte, flags int) (n, oobn in
} }
} }
var rsa RawSockaddrAny var rsa RawSockaddrAny
n, oobn, recvflags, err = recvmsgRaw(fd, iov, oob, flags, &rsa) if n, oobn, recvflags, err = recvmsgRaw(fd, iov, oob, flags, &rsa); err != nil {
if err == nil && rsa.Addr.Family != AF_UNSPEC { return
}
if rsa.Addr.Family != AF_UNSPEC {
from, err = anyToSockaddr(fd, &rsa) from, err = anyToSockaddr(fd, &rsa)
} }
return return

View File

@ -900,6 +900,7 @@ const socket_error = uintptr(^uint32(0))
//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2 //sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2
//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange //sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange
//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2 //sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2
//sys IsProcessorFeaturePresent(ProcessorFeature uint32) (ret bool) = kernel32.IsProcessorFeaturePresent
// For testing: clients can set this flag to force // For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT. // creation of IPv6 sockets to return EAFNOSUPPORT.

View File

@ -3938,3 +3938,88 @@ const (
MOUSE_EVENT = 0x0002 MOUSE_EVENT = 0x0002
WINDOW_BUFFER_SIZE_EVENT = 0x0004 WINDOW_BUFFER_SIZE_EVENT = 0x0004
) )
// The processor features to be tested for IsProcessorFeaturePresent, see
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent
const (
PF_ARM_64BIT_LOADSTORE_ATOMIC = 25
PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE = 24
PF_ARM_EXTERNAL_CACHE_AVAILABLE = 26
PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE = 27
PF_ARM_VFP_32_REGISTERS_AVAILABLE = 18
PF_3DNOW_INSTRUCTIONS_AVAILABLE = 7
PF_CHANNELS_ENABLED = 16
PF_COMPARE_EXCHANGE_DOUBLE = 2
PF_COMPARE_EXCHANGE128 = 14
PF_COMPARE64_EXCHANGE128 = 15
PF_FASTFAIL_AVAILABLE = 23
PF_FLOATING_POINT_EMULATED = 1
PF_FLOATING_POINT_PRECISION_ERRATA = 0
PF_MMX_INSTRUCTIONS_AVAILABLE = 3
PF_NX_ENABLED = 12
PF_PAE_ENABLED = 9
PF_RDTSC_INSTRUCTION_AVAILABLE = 8
PF_RDWRFSGSBASE_AVAILABLE = 22
PF_SECOND_LEVEL_ADDRESS_TRANSLATION = 20
PF_SSE3_INSTRUCTIONS_AVAILABLE = 13
PF_SSSE3_INSTRUCTIONS_AVAILABLE = 36
PF_SSE4_1_INSTRUCTIONS_AVAILABLE = 37
PF_SSE4_2_INSTRUCTIONS_AVAILABLE = 38
PF_AVX_INSTRUCTIONS_AVAILABLE = 39
PF_AVX2_INSTRUCTIONS_AVAILABLE = 40
PF_AVX512F_INSTRUCTIONS_AVAILABLE = 41
PF_VIRT_FIRMWARE_ENABLED = 21
PF_XMMI_INSTRUCTIONS_AVAILABLE = 6
PF_XMMI64_INSTRUCTIONS_AVAILABLE = 10
PF_XSAVE_ENABLED = 17
PF_ARM_V8_INSTRUCTIONS_AVAILABLE = 29
PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE = 30
PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE = 31
PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE = 34
PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE = 43
PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE = 44
PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE = 45
PF_ARM_SVE_INSTRUCTIONS_AVAILABLE = 46
PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE = 47
PF_ARM_SVE2_1_INSTRUCTIONS_AVAILABLE = 48
PF_ARM_SVE_AES_INSTRUCTIONS_AVAILABLE = 49
PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE = 50
PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE = 51
PF_ARM_SVE_BF16_INSTRUCTIONS_AVAILABLE = 52
PF_ARM_SVE_EBF16_INSTRUCTIONS_AVAILABLE = 53
PF_ARM_SVE_B16B16_INSTRUCTIONS_AVAILABLE = 54
PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE = 55
PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE = 56
PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE = 57
PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE = 58
PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE = 59
PF_BMI2_INSTRUCTIONS_AVAILABLE = 60
PF_MOVDIR64B_INSTRUCTION_AVAILABLE = 61
PF_ARM_LSE2_AVAILABLE = 62
PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE = 64
PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE = 65
PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE = 66
PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE = 67
PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE = 68
PF_ARM_V86_EBF16_INSTRUCTIONS_AVAILABLE = 69
PF_ARM_SME_INSTRUCTIONS_AVAILABLE = 70
PF_ARM_SME2_INSTRUCTIONS_AVAILABLE = 71
PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE = 72
PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE = 73
PF_ARM_SME_AES_INSTRUCTIONS_AVAILABLE = 74
PF_ARM_SME_SBITPERM_INSTRUCTIONS_AVAILABLE = 75
PF_ARM_SME_SF8MM4_INSTRUCTIONS_AVAILABLE = 76
PF_ARM_SME_SF8MM8_INSTRUCTIONS_AVAILABLE = 77
PF_ARM_SME_SF8DP2_INSTRUCTIONS_AVAILABLE = 78
PF_ARM_SME_SF8DP4_INSTRUCTIONS_AVAILABLE = 79
PF_ARM_SME_SF8FMA_INSTRUCTIONS_AVAILABLE = 80
PF_ARM_SME_F8F32_INSTRUCTIONS_AVAILABLE = 81
PF_ARM_SME_F8F16_INSTRUCTIONS_AVAILABLE = 82
PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE = 83
PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE = 84
PF_ARM_SME_F64F64_INSTRUCTIONS_AVAILABLE = 85
PF_ARM_SME_I16I64_INSTRUCTIONS_AVAILABLE = 86
PF_ARM_SME_LUTv2_INSTRUCTIONS_AVAILABLE = 87
PF_ARM_SME_FA64_INSTRUCTIONS_AVAILABLE = 88
PF_UMONITOR_INSTRUCTION_AVAILABLE = 89
)

View File

@ -320,6 +320,7 @@ var (
procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW")
procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW") procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW")
procInitializeProcThreadAttributeList = modkernel32.NewProc("InitializeProcThreadAttributeList") procInitializeProcThreadAttributeList = modkernel32.NewProc("InitializeProcThreadAttributeList")
procIsProcessorFeaturePresent = modkernel32.NewProc("IsProcessorFeaturePresent")
procIsWow64Process = modkernel32.NewProc("IsWow64Process") procIsWow64Process = modkernel32.NewProc("IsWow64Process")
procIsWow64Process2 = modkernel32.NewProc("IsWow64Process2") procIsWow64Process2 = modkernel32.NewProc("IsWow64Process2")
procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW")
@ -2786,6 +2787,12 @@ func initializeProcThreadAttributeList(attrlist *ProcThreadAttributeList, attrco
return return
} }
func IsProcessorFeaturePresent(ProcessorFeature uint32) (ret bool) {
r0, _, _ := syscall.SyscallN(procIsProcessorFeaturePresent.Addr(), uintptr(ProcessorFeature))
ret = r0 != 0
return
}
func IsWow64Process(handle Handle, isWow64 *bool) (err error) { func IsWow64Process(handle Handle, isWow64 *bool) (err error) {
var _p0 uint32 var _p0 uint32
if *isWow64 { if *isWow64 {

View File

@ -334,3 +334,7 @@ func (t *Transformer) advanceString(s string) (n int, ok bool) {
} }
return n, true return n, true
} }
func (t *Transformer) isFinal() bool {
return t.state == ruleLTRFinal || t.state == ruleRTLFinal || t.state == ruleInitial
}

View File

@ -1,11 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.10
package bidirule
func (t *Transformer) isFinal() bool {
return t.state == ruleLTRFinal || t.state == ruleRTLFinal || t.state == ruleInitial
}

View File

@ -1,14 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.10
package bidirule
func (t *Transformer) isFinal() bool {
if !t.isRTL() {
return true
}
return t.state == ruleLTRFinal || t.state == ruleRTLFinal || t.state == ruleInitial
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
//go:build go1.21 //go:build !go1.27
package bidi package bidi

2135
vendor/golang.org/x/text/unicode/bidi/tables17.0.0.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,15 +13,18 @@ import "encoding/binary"
// a rune to a uint16. The values take two forms. For v >= 0x8000: // a rune to a uint16. The values take two forms. For v >= 0x8000:
// bits // bits
// 15: 1 (inverse of NFD_QC bit of qcInfo) // 15: 1 (inverse of NFD_QC bit of qcInfo)
// 13..7: qcInfo (see below). isYesD is always true (no decomposition). // 12..7: qcInfo (see below). isYesD is always true (no decomposition).
// 6..0: ccc (compressed CCC value). // 6..0: ccc (compressed CCC value).
// For v < 0x8000, the respective rune has a decomposition and v is an index // For v < 0x8000, the respective rune has a decomposition and v is an index
// into a byte array of UTF-8 decomposition sequences and additional info and // into a byte array of UTF-8 decomposition sequences and additional info and
// has the form: // has the form:
// <header> <decomp_byte>* [<tccc> [<lccc>]] // <header> <decomp_byte>* [<tccc> [<lccc>]]
// The header contains the number of bytes in the decomposition (excluding this // The header contains the number of bytes in the decomposition (excluding this
// length byte). The two most significant bits of this length byte correspond // length byte), with 33 mapped to 31 to fit in 5 bits.
// to bit 5 and 4 of qcInfo (see below). The byte sequence itself starts at v+1. // (If any 31- or 32-byte decompositions come along, we could switch to using
// use a general lookup table as long as there are at most 32 distinct lengths.)
// The three most significant bits of this length byte correspond
// to bit 5, 4, and 3 of qcInfo (see below). The byte sequence itself starts at v+1.
// The byte sequence is followed by a trailing and leading CCC if the values // The byte sequence is followed by a trailing and leading CCC if the values
// for these are not zero. The value of v determines which ccc are appended // for these are not zero. The value of v determines which ccc are appended
// to the sequences. For v < firstCCC, there are none, for v >= firstCCC, // to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
@ -32,8 +35,8 @@ import "encoding/binary"
const ( const (
qcInfoMask = 0x3F // to clear all but the relevant bits in a qcInfo qcInfoMask = 0x3F // to clear all but the relevant bits in a qcInfo
headerLenMask = 0x3F // extract the length value from the header byte headerLenMask = 0x1F // extract the length value from the header byte (31 => 33)
headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte headerFlagsMask = 0xE0 // extract the qcInfo bits from the header byte
) )
// Properties provides access to normalization properties of a rune. // Properties provides access to normalization properties of a rune.
@ -109,14 +112,14 @@ func (p Properties) BoundaryAfter() bool {
return p.isInert() return p.isInert()
} }
// We pack quick check data in 4 bits: // We pack quick check data in 6 bits:
// //
// 5: Combines forward (0 == false, 1 == true) // 5: Combines forward (0 == false, 1 == true)
// 4..3: NFC_QC Yes(00), No (10), or Maybe (11) // 4..3: NFC_QC Yes(00), No (10), or Maybe (11)
// 2: NFD_QC Yes (0) or No (1). No also means there is a decomposition. // 2: NFD_QC Yes (0) or No (1). No also means there is a decomposition.
// 1..0: Number of trailing non-starters. // 1..0: Number of trailing non-starters.
// //
// When all 4 bits are zero, the character is inert, meaning it is never // When all 6 bits are zero, the character is inert, meaning it is never
// influenced by normalization. // influenced by normalization.
type qcInfo uint8 type qcInfo uint8
@ -152,6 +155,9 @@ func (p Properties) Decomposition() []byte {
} }
i := p.index i := p.index
n := decomps[i] & headerLenMask n := decomps[i] & headerLenMask
if n == 31 {
n = 33
}
i++ i++
return decomps[i : i+uint16(n)] return decomps[i : i+uint16(n)]
} }
@ -260,7 +266,11 @@ func compInfo(v uint16, sz int) Properties {
f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4 f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
p := Properties{size: uint8(sz), flags: f, index: v} p := Properties{size: uint8(sz), flags: f, index: v}
if v >= firstCCC { if v >= firstCCC {
v += uint16(h&headerLenMask) + 1 n := uint16(h & headerLenMask)
if n == 31 {
n = 33
}
v += n + 1
c := decomps[v] c := decomps[v]
p.tccc = c >> 2 p.tccc = c >> 2
p.flags |= qcInfo(c & 0x3) p.flags |= qcInfo(c & 0x3)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@ import (
"fmt" "fmt"
"go/ast" "go/ast"
"go/token" "go/token"
"reflect"
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
@ -149,7 +150,7 @@ func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added
if newImport.Name != nil { if newImport.Name != nil {
newImport.Name.NamePos = pos newImport.Name.NamePos = pos
} }
newImport.Path.ValuePos = pos updateBasicLitPos(newImport.Path, pos)
newImport.EndPos = pos newImport.EndPos = pos
// Clean up parens. impDecl contains at least one spec. // Clean up parens. impDecl contains at least one spec.
@ -184,7 +185,7 @@ func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added
first.Lparen = first.Pos() first.Lparen = first.Pos()
// Move the imports of the other import declaration to the first one. // Move the imports of the other import declaration to the first one.
for _, spec := range gen.Specs { for _, spec := range gen.Specs {
spec.(*ast.ImportSpec).Path.ValuePos = first.Pos() updateBasicLitPos(spec.(*ast.ImportSpec).Path, first.Pos())
first.Specs = append(first.Specs, spec) first.Specs = append(first.Specs, spec)
} }
f.Decls = slices.Delete(f.Decls, i, i+1) f.Decls = slices.Delete(f.Decls, i, i+1)
@ -470,3 +471,17 @@ func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec {
return groups return groups
} }
// updateBasicLitPos updates lit.Pos,
// ensuring that lit.End (if set) is displaced by the same amount.
// (See https://go.dev/issue/76395.)
func updateBasicLitPos(lit *ast.BasicLit, pos token.Pos) {
len := lit.End() - lit.Pos()
lit.ValuePos = pos
// TODO(adonovan): after go1.26, simplify to:
// lit.ValueEnd = pos + len
v := reflect.ValueOf(lit).Elem().FieldByName("ValueEnd")
if v.IsValid() && v.Int() != 0 {
v.SetInt(int64(pos + len))
}
}

View File

@ -7,6 +7,7 @@ package core
import ( import (
"fmt" "fmt"
"iter"
"time" "time"
"golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/event/label"
@ -34,11 +35,9 @@ func (ev Event) Format(f fmt.State, r rune) {
if !ev.at.IsZero() { if !ev.at.IsZero() {
fmt.Fprint(f, ev.at.Format("2006/01/02 15:04:05 ")) fmt.Fprint(f, ev.at.Format("2006/01/02 15:04:05 "))
} }
for index := 0; ev.Valid(index); index++ { for l := range ev.Labels() {
if l := ev.Label(index); l.Valid() {
fmt.Fprintf(f, "\n\t%v", l) fmt.Fprintf(f, "\n\t%v", l)
} }
}
} }
func (ev Event) Valid(index int) bool { func (ev Event) Valid(index int) bool {
@ -52,6 +51,22 @@ func (ev Event) Label(index int) label.Label {
return ev.dynamic[index-len(ev.static)] return ev.dynamic[index-len(ev.static)]
} }
// Labels returns an iterator over the event's valid labels.
func (ev Event) Labels() iter.Seq[label.Label] {
return func(yield func(label.Label) bool) {
for _, l := range ev.static {
if l.Valid() && !yield(l) {
return
}
}
for _, l := range ev.dynamic {
if l.Valid() && !yield(l) {
return
}
}
}
}
func (ev Event) Find(key label.Key) label.Label { func (ev Event) Find(key label.Key) label.Label {
for _, l := range ev.static { for _, l := range ev.static {
if l.Key() == key { if l.Key() == key {

View File

@ -8,7 +8,6 @@ import (
"context" "context"
"sync/atomic" "sync/atomic"
"time" "time"
"unsafe"
"golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/event/label"
) )
@ -17,23 +16,21 @@ import (
// It may return a modified context and event. // It may return a modified context and event.
type Exporter func(context.Context, Event, label.Map) context.Context type Exporter func(context.Context, Event, label.Map) context.Context
var ( var exporter atomic.Pointer[Exporter]
exporter unsafe.Pointer
)
// SetExporter sets the global exporter function that handles all events. // SetExporter sets the global exporter function that handles all events.
// The exporter is called synchronously from the event call site, so it should // The exporter is called synchronously from the event call site, so it should
// return quickly so as not to hold up user code. // return quickly so as not to hold up user code.
func SetExporter(e Exporter) { func SetExporter(e Exporter) {
p := unsafe.Pointer(&e)
if e == nil { if e == nil {
// &e is always valid, and so p is always valid, but for the early abort // &e is always valid, and so p is always valid, but for the early abort
// of ProcessEvent to be efficient it needs to make the nil check on the // of ProcessEvent to be efficient it needs to make the nil check on the
// pointer without having to dereference it, so we make the nil function // pointer without having to dereference it, so we make the nil function
// also a nil pointer // also a nil pointer
p = nil exporter.Store(nil)
} else {
exporter.Store(&e)
} }
atomic.StorePointer(&exporter, p)
} }
// deliver is called to deliver an event to the supplied exporter. // deliver is called to deliver an event to the supplied exporter.
@ -48,7 +45,7 @@ func deliver(ctx context.Context, exporter Exporter, ev Event) context.Context {
// Export is called to deliver an event to the global exporter if set. // Export is called to deliver an event to the global exporter if set.
func Export(ctx context.Context, ev Event) context.Context { func Export(ctx context.Context, ev Event) context.Context {
// get the global exporter and abort early if there is not one // get the global exporter and abort early if there is not one
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter)) exporterPtr := exporter.Load()
if exporterPtr == nil { if exporterPtr == nil {
return ctx return ctx
} }
@ -61,7 +58,7 @@ func Export(ctx context.Context, ev Event) context.Context {
// It will fill in the time. // It will fill in the time.
func ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) { func ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) {
// get the global exporter and abort early if there is not one // get the global exporter and abort early if there is not one
exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter)) exporterPtr := exporter.Load()
if exporterPtr == nil { if exporterPtr == nil {
return ctx, func() {} return ctx, func() {}
} }

View File

@ -6,14 +6,13 @@ package keys
import ( import (
"fmt" "fmt"
"io"
"math" "math"
"strconv" "strconv"
"golang.org/x/tools/internal/event/label" "golang.org/x/tools/internal/event/label"
) )
// Value represents a key for untyped values. // Value is a [label.Key] for untyped values.
type Value struct { type Value struct {
name string name string
description string description string
@ -27,11 +26,11 @@ func New(name, description string) *Value {
func (k *Value) Name() string { return k.name } func (k *Value) Name() string { return k.name }
func (k *Value) Description() string { return k.description } func (k *Value) Description() string { return k.description }
func (k *Value) Format(w io.Writer, buf []byte, l label.Label) { func (k *Value) Append(buf []byte, l label.Label) []byte {
fmt.Fprint(w, k.From(l)) return fmt.Append(buf, k.From(l))
} }
// Get can be used to get a label for the key from a label.Map. // Get returns the label for the key of a label.Map.
func (k *Value) Get(lm label.Map) any { func (k *Value) Get(lm label.Map) any {
if t := lm.Find(k); t.Valid() { if t := lm.Find(k); t.Valid() {
return k.From(t) return k.From(t)
@ -39,7 +38,7 @@ func (k *Value) Get(lm label.Map) any {
return nil return nil
} }
// From can be used to get a value from a Label. // From returns the value of a Label.
func (k *Value) From(t label.Label) any { return t.UnpackValue() } func (k *Value) From(t label.Label) any { return t.UnpackValue() }
// Of creates a new Label with this key and the supplied value. // Of creates a new Label with this key and the supplied value.
@ -54,7 +53,7 @@ type Tag struct {
description string description string
} }
// NewTag creates a new Key for tagging labels. // NewTag creates a new [label.Key] for tagging labels.
func NewTag(name, description string) *Tag { func NewTag(name, description string) *Tag {
return &Tag{name: name, description: description} return &Tag{name: name, description: description}
} }
@ -62,18 +61,18 @@ func NewTag(name, description string) *Tag {
func (k *Tag) Name() string { return k.name } func (k *Tag) Name() string { return k.name }
func (k *Tag) Description() string { return k.description } func (k *Tag) Description() string { return k.description }
func (k *Tag) Format(w io.Writer, buf []byte, l label.Label) {} func (k *Tag) Append(buf []byte, l label.Label) []byte { return buf }
// New creates a new Label with this key. // New creates a new Label with this key.
func (k *Tag) New() label.Label { return label.OfValue(k, nil) } func (k *Tag) New() label.Label { return label.OfValue(k, nil) }
// Int represents a key // Int is a [label.Key] for signed integers.
type Int struct { type Int struct {
name string name string
description string description string
} }
// NewInt creates a new Key for int values. // NewInt returns a new [label.Key] for int64 values.
func NewInt(name, description string) *Int { func NewInt(name, description string) *Int {
return &Int{name: name, description: description} return &Int{name: name, description: description}
} }
@ -81,381 +80,92 @@ func NewInt(name, description string) *Int {
func (k *Int) Name() string { return k.name } func (k *Int) Name() string { return k.name }
func (k *Int) Description() string { return k.description } func (k *Int) Description() string { return k.description }
func (k *Int) Format(w io.Writer, buf []byte, l label.Label) { func (k *Int) Append(buf []byte, l label.Label) []byte {
w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) return strconv.AppendInt(buf, k.From(l), 10)
} }
// Of creates a new Label with this key and the supplied value. // Of creates a new Label with this key and the supplied value.
func (k *Int) Of(v int) label.Label { return label.Of64(k, uint64(v)) } func (k *Int) Of(v int) label.Label { return k.Of64(int64(v)) }
// Get can be used to get a label for the key from a label.Map. // Of64 creates a new Label with this key and the supplied value.
func (k *Int) Get(lm label.Map) int { func (k *Int) Of64(v int64) label.Label { return label.Of64(k, uint64(v)) }
// Get returns the label for the key of a label.Map.
func (k *Int) Get(lm label.Map) int64 {
if t := lm.Find(k); t.Valid() { if t := lm.Find(k); t.Valid() {
return k.From(t) return k.From(t)
} }
return 0 return 0
} }
// From can be used to get a value from a Label. // From returns the value of a Label.
func (k *Int) From(t label.Label) int { return int(t.Unpack64()) } func (k *Int) From(t label.Label) int64 { return int64(t.Unpack64()) }
// Int8 represents a key // Uint is a [label.Key] for unsigned integers.
type Int8 struct { type Uint struct {
name string name string
description string description string
} }
// NewInt8 creates a new Key for int8 values. // NewUint creates a new [label.Key] for unsigned values.
func NewInt8(name, description string) *Int8 { func NewUint(name, description string) *Uint {
return &Int8{name: name, description: description} return &Uint{name: name, description: description}
} }
func (k *Int8) Name() string { return k.name } func (k *Uint) Name() string { return k.name }
func (k *Int8) Description() string { return k.description } func (k *Uint) Description() string { return k.description }
func (k *Int8) Format(w io.Writer, buf []byte, l label.Label) { func (k *Uint) Append(buf []byte, l label.Label) []byte {
w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) return strconv.AppendUint(buf, k.From(l), 10)
} }
// Of creates a new Label with this key and the supplied value. // Of creates a new Label with this key and the supplied value.
func (k *Int8) Of(v int8) label.Label { return label.Of64(k, uint64(v)) } func (k *Uint) Of(v uint64) label.Label { return label.Of64(k, v) }
// Get can be used to get a label for the key from a label.Map. // Get returns the label for the key of a label.Map.
func (k *Int8) Get(lm label.Map) int8 { func (k *Uint) Get(lm label.Map) uint64 {
if t := lm.Find(k); t.Valid() { if t := lm.Find(k); t.Valid() {
return k.From(t) return k.From(t)
} }
return 0 return 0
} }
// From can be used to get a value from a Label. // From returns the value of a Label.
func (k *Int8) From(t label.Label) int8 { return int8(t.Unpack64()) } func (k *Uint) From(t label.Label) uint64 { return t.Unpack64() }
// Int16 represents a key // Float is a label.Key for floating-point values.
type Int16 struct { type Float struct {
name string name string
description string description string
} }
// NewInt16 creates a new Key for int16 values. // NewFloat creates a new [label.Key] for floating-point values.
func NewInt16(name, description string) *Int16 { func NewFloat(name, description string) *Float {
return &Int16{name: name, description: description} return &Float{name: name, description: description}
} }
func (k *Int16) Name() string { return k.name } func (k *Float) Name() string { return k.name }
func (k *Int16) Description() string { return k.description } func (k *Float) Description() string { return k.description }
func (k *Int16) Format(w io.Writer, buf []byte, l label.Label) { func (k *Float) Append(buf []byte, l label.Label) []byte {
w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10)) return strconv.AppendFloat(buf, k.From(l), 'E', -1, 64)
} }
// Of creates a new Label with this key and the supplied value. // Of creates a new Label with this key and the supplied value.
func (k *Int16) Of(v int16) label.Label { return label.Of64(k, uint64(v)) } func (k *Float) Of(v float64) label.Label {
// Get can be used to get a label for the key from a label.Map.
func (k *Int16) Get(lm label.Map) int16 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *Int16) From(t label.Label) int16 { return int16(t.Unpack64()) }
// Int32 represents a key
type Int32 struct {
name string
description string
}
// NewInt32 creates a new Key for int32 values.
func NewInt32(name, description string) *Int32 {
return &Int32{name: name, description: description}
}
func (k *Int32) Name() string { return k.name }
func (k *Int32) Description() string { return k.description }
func (k *Int32) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10))
}
// Of creates a new Label with this key and the supplied value.
func (k *Int32) Of(v int32) label.Label { return label.Of64(k, uint64(v)) }
// Get can be used to get a label for the key from a label.Map.
func (k *Int32) Get(lm label.Map) int32 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *Int32) From(t label.Label) int32 { return int32(t.Unpack64()) }
// Int64 represents a key
type Int64 struct {
name string
description string
}
// NewInt64 creates a new Key for int64 values.
func NewInt64(name, description string) *Int64 {
return &Int64{name: name, description: description}
}
func (k *Int64) Name() string { return k.name }
func (k *Int64) Description() string { return k.description }
func (k *Int64) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendInt(buf, k.From(l), 10))
}
// Of creates a new Label with this key and the supplied value.
func (k *Int64) Of(v int64) label.Label { return label.Of64(k, uint64(v)) }
// Get can be used to get a label for the key from a label.Map.
func (k *Int64) Get(lm label.Map) int64 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *Int64) From(t label.Label) int64 { return int64(t.Unpack64()) }
// UInt represents a key
type UInt struct {
name string
description string
}
// NewUInt creates a new Key for uint values.
func NewUInt(name, description string) *UInt {
return &UInt{name: name, description: description}
}
func (k *UInt) Name() string { return k.name }
func (k *UInt) Description() string { return k.description }
func (k *UInt) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
}
// Of creates a new Label with this key and the supplied value.
func (k *UInt) Of(v uint) label.Label { return label.Of64(k, uint64(v)) }
// Get can be used to get a label for the key from a label.Map.
func (k *UInt) Get(lm label.Map) uint {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *UInt) From(t label.Label) uint { return uint(t.Unpack64()) }
// UInt8 represents a key
type UInt8 struct {
name string
description string
}
// NewUInt8 creates a new Key for uint8 values.
func NewUInt8(name, description string) *UInt8 {
return &UInt8{name: name, description: description}
}
func (k *UInt8) Name() string { return k.name }
func (k *UInt8) Description() string { return k.description }
func (k *UInt8) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
}
// Of creates a new Label with this key and the supplied value.
func (k *UInt8) Of(v uint8) label.Label { return label.Of64(k, uint64(v)) }
// Get can be used to get a label for the key from a label.Map.
func (k *UInt8) Get(lm label.Map) uint8 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *UInt8) From(t label.Label) uint8 { return uint8(t.Unpack64()) }
// UInt16 represents a key
type UInt16 struct {
name string
description string
}
// NewUInt16 creates a new Key for uint16 values.
func NewUInt16(name, description string) *UInt16 {
return &UInt16{name: name, description: description}
}
func (k *UInt16) Name() string { return k.name }
func (k *UInt16) Description() string { return k.description }
func (k *UInt16) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
}
// Of creates a new Label with this key and the supplied value.
func (k *UInt16) Of(v uint16) label.Label { return label.Of64(k, uint64(v)) }
// Get can be used to get a label for the key from a label.Map.
func (k *UInt16) Get(lm label.Map) uint16 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *UInt16) From(t label.Label) uint16 { return uint16(t.Unpack64()) }
// UInt32 represents a key
type UInt32 struct {
name string
description string
}
// NewUInt32 creates a new Key for uint32 values.
func NewUInt32(name, description string) *UInt32 {
return &UInt32{name: name, description: description}
}
func (k *UInt32) Name() string { return k.name }
func (k *UInt32) Description() string { return k.description }
func (k *UInt32) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
}
// Of creates a new Label with this key and the supplied value.
func (k *UInt32) Of(v uint32) label.Label { return label.Of64(k, uint64(v)) }
// Get can be used to get a label for the key from a label.Map.
func (k *UInt32) Get(lm label.Map) uint32 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *UInt32) From(t label.Label) uint32 { return uint32(t.Unpack64()) }
// UInt64 represents a key
type UInt64 struct {
name string
description string
}
// NewUInt64 creates a new Key for uint64 values.
func NewUInt64(name, description string) *UInt64 {
return &UInt64{name: name, description: description}
}
func (k *UInt64) Name() string { return k.name }
func (k *UInt64) Description() string { return k.description }
func (k *UInt64) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendUint(buf, k.From(l), 10))
}
// Of creates a new Label with this key and the supplied value.
func (k *UInt64) Of(v uint64) label.Label { return label.Of64(k, v) }
// Get can be used to get a label for the key from a label.Map.
func (k *UInt64) Get(lm label.Map) uint64 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *UInt64) From(t label.Label) uint64 { return t.Unpack64() }
// Float32 represents a key
type Float32 struct {
name string
description string
}
// NewFloat32 creates a new Key for float32 values.
func NewFloat32(name, description string) *Float32 {
return &Float32{name: name, description: description}
}
func (k *Float32) Name() string { return k.name }
func (k *Float32) Description() string { return k.description }
func (k *Float32) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendFloat(buf, float64(k.From(l)), 'E', -1, 32))
}
// Of creates a new Label with this key and the supplied value.
func (k *Float32) Of(v float32) label.Label {
return label.Of64(k, uint64(math.Float32bits(v)))
}
// Get can be used to get a label for the key from a label.Map.
func (k *Float32) Get(lm label.Map) float32 {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return 0
}
// From can be used to get a value from a Label.
func (k *Float32) From(t label.Label) float32 {
return math.Float32frombits(uint32(t.Unpack64()))
}
// Float64 represents a key
type Float64 struct {
name string
description string
}
// NewFloat64 creates a new Key for int64 values.
func NewFloat64(name, description string) *Float64 {
return &Float64{name: name, description: description}
}
func (k *Float64) Name() string { return k.name }
func (k *Float64) Description() string { return k.description }
func (k *Float64) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendFloat(buf, k.From(l), 'E', -1, 64))
}
// Of creates a new Label with this key and the supplied value.
func (k *Float64) Of(v float64) label.Label {
return label.Of64(k, math.Float64bits(v)) return label.Of64(k, math.Float64bits(v))
} }
// Get can be used to get a label for the key from a label.Map. // Get returns the label for the key of a label.Map.
func (k *Float64) Get(lm label.Map) float64 { func (k *Float) Get(lm label.Map) float64 {
if t := lm.Find(k); t.Valid() { if t := lm.Find(k); t.Valid() {
return k.From(t) return k.From(t)
} }
return 0 return 0
} }
// From can be used to get a value from a Label. // From returns the value of a Label.
func (k *Float64) From(t label.Label) float64 { func (k *Float) From(t label.Label) float64 {
return math.Float64frombits(t.Unpack64()) return math.Float64frombits(t.Unpack64())
} }
@ -473,14 +183,14 @@ func NewString(name, description string) *String {
func (k *String) Name() string { return k.name } func (k *String) Name() string { return k.name }
func (k *String) Description() string { return k.description } func (k *String) Description() string { return k.description }
func (k *String) Format(w io.Writer, buf []byte, l label.Label) { func (k *String) Append(buf []byte, l label.Label) []byte {
w.Write(strconv.AppendQuote(buf, k.From(l))) return strconv.AppendQuote(buf, k.From(l))
} }
// Of creates a new Label with this key and the supplied value. // Of creates a new Label with this key and the supplied value.
func (k *String) Of(v string) label.Label { return label.OfString(k, v) } func (k *String) Of(v string) label.Label { return label.OfString(k, v) }
// Get can be used to get a label for the key from a label.Map. // Get returns the label for the key of a label.Map.
func (k *String) Get(lm label.Map) string { func (k *String) Get(lm label.Map) string {
if t := lm.Find(k); t.Valid() { if t := lm.Find(k); t.Valid() {
return k.From(t) return k.From(t)
@ -488,53 +198,16 @@ func (k *String) Get(lm label.Map) string {
return "" return ""
} }
// From can be used to get a value from a Label. // From returns the value of a Label.
func (k *String) From(t label.Label) string { return t.UnpackString() } func (k *String) From(t label.Label) string { return t.UnpackString() }
// Boolean represents a key
type Boolean struct {
name string
description string
}
// NewBoolean creates a new Key for bool values.
func NewBoolean(name, description string) *Boolean {
return &Boolean{name: name, description: description}
}
func (k *Boolean) Name() string { return k.name }
func (k *Boolean) Description() string { return k.description }
func (k *Boolean) Format(w io.Writer, buf []byte, l label.Label) {
w.Write(strconv.AppendBool(buf, k.From(l)))
}
// Of creates a new Label with this key and the supplied value.
func (k *Boolean) Of(v bool) label.Label {
if v {
return label.Of64(k, 1)
}
return label.Of64(k, 0)
}
// Get can be used to get a label for the key from a label.Map.
func (k *Boolean) Get(lm label.Map) bool {
if t := lm.Find(k); t.Valid() {
return k.From(t)
}
return false
}
// From can be used to get a value from a Label.
func (k *Boolean) From(t label.Label) bool { return t.Unpack64() > 0 }
// Error represents a key // Error represents a key
type Error struct { type Error struct {
name string name string
description string description string
} }
// NewError creates a new Key for int64 values. // NewError returns a new [label.Key] for error values.
func NewError(name, description string) *Error { func NewError(name, description string) *Error {
return &Error{name: name, description: description} return &Error{name: name, description: description}
} }
@ -542,14 +215,14 @@ func NewError(name, description string) *Error {
func (k *Error) Name() string { return k.name } func (k *Error) Name() string { return k.name }
func (k *Error) Description() string { return k.description } func (k *Error) Description() string { return k.description }
func (k *Error) Format(w io.Writer, buf []byte, l label.Label) { func (k *Error) Append(buf []byte, l label.Label) []byte {
io.WriteString(w, k.From(l).Error()) return append(buf, k.From(l).Error()...)
} }
// Of creates a new Label with this key and the supplied value. // Of returns a new Label with this key and the supplied value.
func (k *Error) Of(v error) label.Label { return label.OfValue(k, v) } func (k *Error) Of(v error) label.Label { return label.OfValue(k, v) }
// Get can be used to get a label for the key from a label.Map. // Get returns the label for the key of a label.Map.
func (k *Error) Get(lm label.Map) error { func (k *Error) Get(lm label.Map) error {
if t := lm.Find(k); t.Valid() { if t := lm.Find(k); t.Valid() {
return k.From(t) return k.From(t)
@ -557,7 +230,7 @@ func (k *Error) Get(lm label.Map) error {
return nil return nil
} }
// From can be used to get a value from a Label. // From returns the value of a Label.
func (k *Error) From(t label.Label) error { func (k *Error) From(t label.Label) error {
err, _ := t.UnpackValue().(error) err, _ := t.UnpackValue().(error)
return err return err

View File

@ -7,7 +7,6 @@ package label
import ( import (
"fmt" "fmt"
"io" "io"
"reflect"
"slices" "slices"
"unsafe" "unsafe"
) )
@ -20,12 +19,8 @@ type Key interface {
Name() string Name() string
// Description returns a string that can be used to describe the value. // Description returns a string that can be used to describe the value.
Description() string Description() string
// Append appends the formatted value of the label to the supplied buffer.
// Format is used in formatting to append the value of the label to the Append(buf []byte, l Label) []byte
// supplied buffer.
// The formatter may use the supplied buf as a scratch area to avoid
// allocations.
Format(w io.Writer, buf []byte, l Label)
} }
// Label holds a key and value pair. // Label holds a key and value pair.
@ -103,11 +98,10 @@ type stringptr unsafe.Pointer
// This method is for implementing new key types, label creation should // This method is for implementing new key types, label creation should
// normally be done with the Of method of the key. // normally be done with the Of method of the key.
func OfString(k Key, v string) Label { func OfString(k Key, v string) Label {
hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
return Label{ return Label{
key: k, key: k,
packed: uint64(hdr.Len), packed: uint64(len(v)),
untyped: stringptr(hdr.Data), untyped: stringptr(unsafe.StringData(v)),
} }
} }
@ -116,11 +110,7 @@ func OfString(k Key, v string) Label {
// This method is for implementing new key types, for type safety normal // This method is for implementing new key types, for type safety normal
// access should be done with the From method of the key. // access should be done with the From method of the key.
func (t Label) UnpackString() string { func (t Label) UnpackString() string {
var v string return unsafe.String((*byte)(t.untyped.(stringptr)), int(t.packed))
hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
hdr.Data = uintptr(t.untyped.(stringptr))
hdr.Len = int(t.packed)
return v
} }
// Valid returns true if the Label is a valid one (it has a key). // Valid returns true if the Label is a valid one (it has a key).
@ -137,8 +127,7 @@ func (t Label) Format(f fmt.State, r rune) {
} }
io.WriteString(f, t.Key().Name()) io.WriteString(f, t.Key().Name())
io.WriteString(f, "=") io.WriteString(f, "=")
var buf [128]byte f.Write(t.Key().Append(nil, t)) // ignore error
t.Key().Format(f, buf[:0], t)
} }
func (l *list) Valid(index int) bool { func (l *list) Valid(index int) bool {

View File

@ -11,6 +11,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
"log" "log"
"reflect"
"slices" "slices"
"sort" "sort"
"strconv" "strconv"
@ -65,7 +66,7 @@ func sortImports(localPrefix string, tokFile *token.File, f *ast.File) {
} }
// mergeImports merges all the import declarations into the first one. // mergeImports merges all the import declarations into the first one.
// Taken from golang.org/x/tools/ast/astutil. // Taken from golang.org/x/tools/go/ast/astutil.
// This does not adjust line numbers properly // This does not adjust line numbers properly
func mergeImports(f *ast.File) { func mergeImports(f *ast.File) {
if len(f.Decls) <= 1 { if len(f.Decls) <= 1 {
@ -89,7 +90,7 @@ func mergeImports(f *ast.File) {
first.Lparen = first.Pos() first.Lparen = first.Pos()
// Move the imports of the other import declaration to the first one. // Move the imports of the other import declaration to the first one.
for _, spec := range gen.Specs { for _, spec := range gen.Specs {
spec.(*ast.ImportSpec).Path.ValuePos = first.Pos() updateBasicLitPos(spec.(*ast.ImportSpec).Path, first.Pos())
first.Specs = append(first.Specs, spec) first.Specs = append(first.Specs, spec)
} }
f.Decls = slices.Delete(f.Decls, i, i+1) f.Decls = slices.Delete(f.Decls, i, i+1)
@ -98,7 +99,7 @@ func mergeImports(f *ast.File) {
} }
// declImports reports whether gen contains an import of path. // declImports reports whether gen contains an import of path.
// Taken from golang.org/x/tools/ast/astutil. // Taken from golang.org/x/tools/go/ast/astutil.
func declImports(gen *ast.GenDecl, path string) bool { func declImports(gen *ast.GenDecl, path string) bool {
if gen.Tok != token.IMPORT { if gen.Tok != token.IMPORT {
return false return false
@ -221,7 +222,7 @@ func sortSpecs(localPrefix string, tokFile *token.File, f *ast.File, specs []ast
if s.Name != nil { if s.Name != nil {
s.Name.NamePos = pos[i].Start s.Name.NamePos = pos[i].Start
} }
s.Path.ValuePos = pos[i].Start updateBasicLitPos(s.Path, pos[i].Start)
s.EndPos = pos[i].End s.EndPos = pos[i].End
nextSpecPos := pos[i].End nextSpecPos := pos[i].End
@ -296,3 +297,17 @@ type byCommentPos []*ast.CommentGroup
func (x byCommentPos) Len() int { return len(x) } func (x byCommentPos) Len() int { return len(x) }
func (x byCommentPos) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x byCommentPos) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() } func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
// updateBasicLitPos updates lit.Pos,
// ensuring that lit.End (if set) is displaced by the same amount.
// (See https://go.dev/issue/76395.)
func updateBasicLitPos(lit *ast.BasicLit, pos token.Pos) {
len := lit.End() - lit.Pos()
lit.ValuePos = pos
// TODO(adonovan): after go1.26, simplify to:
// lit.ValueEnd = pos + len
v := reflect.ValueOf(lit).Elem().FieldByName("ValueEnd")
if v.IsValid() && v.Int() != 0 {
v.SetInt(int64(pos + len))
}
}

View File

@ -10,7 +10,6 @@ import (
"encoding/csv" "encoding/csv"
"fmt" "fmt"
"io" "io"
"log"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -107,14 +106,14 @@ var IndexDir string = func() string {
var err error var err error
dir, err = os.UserCacheDir() dir, err = os.UserCacheDir()
// shouldn't happen, but TempDir is better than // shouldn't happen, but TempDir is better than
// creating ./go/imports // creating ./goimports
if err != nil { if err != nil {
dir = os.TempDir() dir = os.TempDir()
} }
} }
dir = filepath.Join(dir, "goimports") dir = filepath.Join(dir, "goimports")
if err := os.MkdirAll(dir, 0777); err != nil { if err := os.MkdirAll(dir, 0777); err != nil {
log.Printf("failed to create modcache index dir: %v", err) dir = "" // #75505, people complain about the error message
} }
return dir return dir
}() }()
@ -127,6 +126,9 @@ func Read(gomodcache string) (*Index, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if IndexDir == "" {
return nil, os.ErrNotExist
}
// Read the "link" file for the specified gomodcache directory. // Read the "link" file for the specified gomodcache directory.
// It names the payload file. // It names the payload file.
@ -227,6 +229,9 @@ func readIndexFrom(gomodcache string, r io.Reader) (*Index, error) {
// write writes the index file and updates the index directory to refer to it. // write writes the index file and updates the index directory to refer to it.
func write(gomodcache string, ix *Index) error { func write(gomodcache string, ix *Index) error {
if IndexDir == "" {
return os.ErrNotExist
}
// Write the index into a payload file with a fresh name. // Write the index into a payload file with a fresh name.
f, err := os.CreateTemp(IndexDir, fmt.Sprintf("index-%d-*", CurrentVersion)) f, err := os.CreateTemp(IndexDir, fmt.Sprintf("index-%d-*", CurrentVersion))
if err != nil { if err != nil {

View File

@ -8,6 +8,8 @@ import (
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
"golang.org/x/mod/module"
) )
type Candidate struct { type Candidate struct {
@ -104,11 +106,15 @@ func (ix *Index) Lookup(pkgName, name string, prefix bool) []Candidate {
if len(flds) < 2 { if len(flds) < 2 {
continue // should never happen continue // should never happen
} }
impPath, err := module.UnescapePath(e.ImportPath)
if err != nil {
continue
}
px := Candidate{ px := Candidate{
PkgName: pkgName, PkgName: pkgName,
Name: flds[0], Name: flds[0],
Dir: string(e.Dir), Dir: string(e.Dir),
ImportPath: e.ImportPath, ImportPath: impPath,
Type: asLexType(flds[1][0]), Type: asLexType(flds[1][0]),
Deprecated: len(flds[1]) > 1 && flds[1][1] == 'D', Deprecated: len(flds[1]) > 1 && flds[1][1] == 'D',
} }

View File

@ -12,360 +12,366 @@ type pkginfo struct {
} }
var deps = [...]pkginfo{ var deps = [...]pkginfo{
{"archive/tar", "\x03n\x03E<\x01\n\x01$\x01\x01\x02\x05\b\x02\x01\x02\x02\f"}, {"archive/tar", "\x03q\x03F=\x01\n\x01$\x01\x01\x02\x05\b\x02\x01\x02\x02\r"},
{"archive/zip", "\x02\x04d\a\x03\x12\x021<\x01+\x05\x01\x0f\x03\x02\x0e\x04"}, {"archive/zip", "\x02\x04g\a\x03\x13\x021=\x01+\x05\x01\x0f\x03\x02\x0f\x04"},
{"bufio", "\x03n\x84\x01D\x14"}, {"bufio", "\x03q\x86\x01D\x15"},
{"bytes", "q*Z\x03\fG\x02\x02"}, {"bytes", "t+[\x03\fH\x02\x02"},
{"cmp", ""}, {"cmp", ""},
{"compress/bzip2", "\x02\x02\xf1\x01A"}, {"compress/bzip2", "\x02\x02\xf6\x01A"},
{"compress/flate", "\x02o\x03\x81\x01\f\x033\x01\x03"}, {"compress/flate", "\x02r\x03\x83\x01\f\x033\x01\x03"},
{"compress/gzip", "\x02\x04d\a\x03\x14mT"}, {"compress/gzip", "\x02\x04g\a\x03\x15nU"},
{"compress/lzw", "\x02o\x03\x81\x01"}, {"compress/lzw", "\x02r\x03\x83\x01"},
{"compress/zlib", "\x02\x04d\a\x03\x12\x01n"}, {"compress/zlib", "\x02\x04g\a\x03\x13\x01o"},
{"container/heap", "\xb7\x02"}, {"container/heap", "\xbc\x02"},
{"container/list", ""}, {"container/list", ""},
{"container/ring", ""}, {"container/ring", ""},
{"context", "q[o\x01\r"}, {"context", "t\\p\x01\x0e"},
{"crypto", "\x86\x01oC"}, {"crypto", "\x8a\x01pC"},
{"crypto/aes", "\x10\n\t\x95\x02"}, {"crypto/aes", "\x10\v\t\x99\x02"},
{"crypto/cipher", "\x03 \x01\x01\x1f\x11\x1c+Y"}, {"crypto/cipher", "\x03!\x01\x01 \x12\x1c,Z"},
{"crypto/des", "\x10\x15\x1f-+\x9c\x01\x03"}, {"crypto/des", "\x10\x16 .,\x9d\x01\x03"},
{"crypto/dsa", "D\x04)\x84\x01\r"}, {"crypto/dsa", "F\x03+\x86\x01\r"},
{"crypto/ecdh", "\x03\v\f\x10\x04\x16\x04\r\x1c\x84\x01"}, {"crypto/ecdh", "\x03\v\r\x10\x04\x17\x03\x0f\x1c\x86\x01"},
{"crypto/ecdsa", "\x0e\x05\x03\x04\x01\x10\a\v\x06\x01\x04\f\x01\x1c\x84\x01\r\x05K\x01"}, {"crypto/ecdsa", "\x0e\x05\x03\x05\x01\x10\b\v\x06\x01\x03\x0e\x01\x1c\x86\x01\r\x05L\x01"},
{"crypto/ed25519", "\x0e\x1e\x11\a\n\a\x1c\x84\x01C"}, {"crypto/ed25519", "\x0e\x1f\x12\a\x03\b\a\x1cI=C"},
{"crypto/elliptic", "2?\x84\x01\r9"}, {"crypto/elliptic", "4@\x86\x01\r9"},
{"crypto/fips140", "\"\x05"}, {"crypto/fips140", "#\x05\x95\x01\x98\x01"},
{"crypto/hkdf", "/\x14\x01-\x15"}, {"crypto/hkdf", "0\x15\x01.\x16"},
{"crypto/hmac", "\x1a\x16\x13\x01\x111"}, {"crypto/hmac", "\x1b\x16\x14\x01\x122"},
{"crypto/internal/boring", "\x0e\x02\ri"}, {"crypto/hpke", "\x03\v\x02\x03\x04\x01\f\x01\x05\x1f\x05\a\x01\x01\x1d\x03\x13\x16\x9b\x01\x1c"},
{"crypto/internal/boring/bbig", "\x1a\xe8\x01M"}, {"crypto/internal/boring", "\x0e\x02\x0el"},
{"crypto/internal/boring/bcache", "\xbc\x02\x13"}, {"crypto/internal/boring/bbig", "\x1b\xec\x01N"},
{"crypto/internal/boring/bcache", "\xc1\x02\x14"},
{"crypto/internal/boring/sig", ""}, {"crypto/internal/boring/sig", ""},
{"crypto/internal/constanttime", ""}, {"crypto/internal/constanttime", ""},
{"crypto/internal/cryptotest", "\x03\r\n\b%\x0e\x19\x06\x12\x12 \x04\x06\t\x18\x01\x11\x11\x1b\x01\a\x05\b\x03\x05\v"}, {"crypto/internal/cryptotest", "\x03\r\v\b%\x10\x19\x06\x13\x12 \x04\x06\t\x19\x01\x11\x11\x1b\x01\a\x05\b\x03\x05\f"},
{"crypto/internal/entropy", "I"}, {"crypto/internal/entropy", "K"},
{"crypto/internal/entropy/v1.0.0", "B/\x93\x018\x13"}, {"crypto/internal/entropy/v1.0.0", "D0\x95\x018\x14"},
{"crypto/internal/fips140", "A0\xbd\x01\v\x16"}, {"crypto/internal/fips140", "C1\xbf\x01\v\x17"},
{"crypto/internal/fips140/aes", "\x03\x1f\x03\x02\x13\x05\x01\x01\x06*\x93\x014"}, {"crypto/internal/fips140/aes", "\x03 \x03\x02\x14\x05\x01\x01\x05,\x95\x014"},
{"crypto/internal/fips140/aes/gcm", "\"\x01\x02\x02\x02\x11\x05\x01\a*\x90\x01"}, {"crypto/internal/fips140/aes/gcm", "#\x01\x02\x02\x02\x12\x05\x01\x06,\x92\x01"},
{"crypto/internal/fips140/alias", "\xcf\x02"}, {"crypto/internal/fips140/alias", "\xd5\x02"},
{"crypto/internal/fips140/bigmod", "'\x18\x01\a*\x93\x01"}, {"crypto/internal/fips140/bigmod", "(\x19\x01\x06,\x95\x01"},
{"crypto/internal/fips140/check", "\"\x0e\x06\t\x02\xb4\x01Z"}, {"crypto/internal/fips140/check", "#\x0e\a\t\x02\xb7\x01["},
{"crypto/internal/fips140/check/checktest", "'\x87\x02!"}, {"crypto/internal/fips140/check/checktest", "(\x8b\x02\""},
{"crypto/internal/fips140/drbg", "\x03\x1e\x01\x01\x04\x13\x05\t\x01(\x84\x01\x0f7\x01"}, {"crypto/internal/fips140/drbg", "\x03\x1f\x01\x01\x04\x14\x05\n)\x86\x01\x0f7\x01"},
{"crypto/internal/fips140/ecdh", "\x03\x1f\x05\x02\t\r2\x84\x01\x0f7"}, {"crypto/internal/fips140/ecdh", "\x03 \x05\x02\n\r3\x86\x01\x0f7"},
{"crypto/internal/fips140/ecdsa", "\x03\x1f\x04\x01\x02\a\x02\x069\x15oF"}, {"crypto/internal/fips140/ecdsa", "\x03 \x04\x01\x02\a\x03\x06:\x16pF"},
{"crypto/internal/fips140/ed25519", "\x03\x1f\x05\x02\x04\v9\xc7\x01\x03"}, {"crypto/internal/fips140/ed25519", "\x03 \x05\x02\x04\f:\xc9\x01\x03"},
{"crypto/internal/fips140/edwards25519", "\x1e\t\a\x112\x93\x017"}, {"crypto/internal/fips140/edwards25519", "\x1f\t\a\x123\x95\x017"},
{"crypto/internal/fips140/edwards25519/field", "'\x13\x052\x93\x01"}, {"crypto/internal/fips140/edwards25519/field", "(\x14\x053\x95\x01"},
{"crypto/internal/fips140/hkdf", "\x03\x1f\x05\t\x06;\x15"}, {"crypto/internal/fips140/hkdf", "\x03 \x05\t\a<\x16"},
{"crypto/internal/fips140/hmac", "\x03\x1f\x14\x01\x019\x15"}, {"crypto/internal/fips140/hmac", "\x03 \x15\x01\x01:\x16"},
{"crypto/internal/fips140/mlkem", "\x03\x1f\x05\x02\x0e\x03\x052\xca\x01"}, {"crypto/internal/fips140/mldsa", "\x03\x1c\x04\x05\x02\x0e\x01\x03\x053\x95\x017"},
{"crypto/internal/fips140/nistec", "\x1e\t\f\f2\x93\x01*\r\x14"}, {"crypto/internal/fips140/mlkem", "\x03 \x05\x02\x0f\x03\x053\xcc\x01"},
{"crypto/internal/fips140/nistec/fiat", "'\x137\x93\x01"}, {"crypto/internal/fips140/nistec", "\x1f\t\r\f3\x95\x01*\r\x15"},
{"crypto/internal/fips140/pbkdf2", "\x03\x1f\x05\t\x06;\x15"}, {"crypto/internal/fips140/nistec/fiat", "(\x148\x95\x01"},
{"crypto/internal/fips140/rsa", "\x03\x1b\x04\x04\x01\x02\r\x01\x01\x027\x15oF"}, {"crypto/internal/fips140/pbkdf2", "\x03 \x05\t\a<\x16"},
{"crypto/internal/fips140/sha256", "\x03\x1f\x1d\x01\a*\x15~"}, {"crypto/internal/fips140/rsa", "\x03\x1c\x04\x04\x01\x02\x0e\x01\x01\x028\x16pF"},
{"crypto/internal/fips140/sha3", "\x03\x1f\x18\x05\x011\x93\x01K"}, {"crypto/internal/fips140/sha256", "\x03 \x1e\x01\x06,\x16\x7f"},
{"crypto/internal/fips140/sha512", "\x03\x1f\x1d\x01\a*\x15~"}, {"crypto/internal/fips140/sha3", "\x03 \x19\x05\x012\x95\x01L"},
{"crypto/internal/fips140/ssh", "'_"}, {"crypto/internal/fips140/sha512", "\x03 \x1e\x01\x06,\x16\x7f"},
{"crypto/internal/fips140/subtle", "\x1e\a\x1a\xc5\x01"}, {"crypto/internal/fips140/ssh", "(b"},
{"crypto/internal/fips140/tls12", "\x03\x1f\x05\t\x06\x029\x15"}, {"crypto/internal/fips140/subtle", "\x1f\a\x1b\xc8\x01"},
{"crypto/internal/fips140/tls13", "\x03\x1f\x05\b\a\t2\x15"}, {"crypto/internal/fips140/tls12", "\x03 \x05\t\a\x02:\x16"},
{"crypto/internal/fips140cache", "\xae\x02\r&"}, {"crypto/internal/fips140/tls13", "\x03 \x05\b\b\t3\x16"},
{"crypto/internal/fips140cache", "\xb3\x02\r'"},
{"crypto/internal/fips140deps", ""}, {"crypto/internal/fips140deps", ""},
{"crypto/internal/fips140deps/byteorder", "\x9c\x01"}, {"crypto/internal/fips140deps/byteorder", "\xa0\x01"},
{"crypto/internal/fips140deps/cpu", "\xb1\x01\a"}, {"crypto/internal/fips140deps/cpu", "\xb5\x01\a"},
{"crypto/internal/fips140deps/godebug", "\xb9\x01"}, {"crypto/internal/fips140deps/godebug", "\xbd\x01"},
{"crypto/internal/fips140deps/time", "\xc9\x02"}, {"crypto/internal/fips140deps/time", "\xcf\x02"},
{"crypto/internal/fips140hash", "7\x1c3\xc9\x01"}, {"crypto/internal/fips140hash", "9\x1d4\xcb\x01"},
{"crypto/internal/fips140only", ")\r\x01\x01N3<"}, {"crypto/internal/fips140only", "\x17\x13\x0e\x01\x01Pp"},
{"crypto/internal/fips140test", ""}, {"crypto/internal/fips140test", ""},
{"crypto/internal/hpke", "\x0e\x01\x01\x03\x056#+hM"}, {"crypto/internal/impl", "\xbe\x02"},
{"crypto/internal/impl", "\xb9\x02"}, {"crypto/internal/rand", "\x1b\x0f s=["},
{"crypto/internal/randutil", "\xf5\x01\x12"}, {"crypto/internal/randutil", "\xfa\x01\x12"},
{"crypto/internal/sysrand", "qo! \r\r\x01\x01\f\x06"}, {"crypto/internal/sysrand", "tq! \r\r\x01\x01\r\x06"},
{"crypto/internal/sysrand/internal/seccomp", "q"}, {"crypto/internal/sysrand/internal/seccomp", "t"},
{"crypto/md5", "\x0e6-\x15\x16h"}, {"crypto/md5", "\x0e8.\x16\x16i"},
{"crypto/mlkem", "1"}, {"crypto/mlkem", "\x0e%"},
{"crypto/pbkdf2", "4\x0f\x01-\x15"}, {"crypto/mlkem/mlkemtest", "3\x13\b&"},
{"crypto/rand", "\x1a\b\a\x1b\x04\x01(\x84\x01\rM"}, {"crypto/pbkdf2", "6\x0f\x01.\x16"},
{"crypto/rc4", "%\x1f-\xc7\x01"}, {"crypto/rand", "\x1b\x0f\x1c\x03+\x86\x01\rN"},
{"crypto/rsa", "\x0e\f\x01\v\x0f\x0e\x01\x04\x06\a\x1c\x03\x123<\f\x01"}, {"crypto/rc4", "& .\xc9\x01"},
{"crypto/sha1", "\x0e\f*\x03*\x15\x16\x15S"}, {"crypto/rsa", "\x0e\r\x01\v\x10\x0e\x01\x03\b\a\x1c\x03\x133=\f\x01"},
{"crypto/sha256", "\x0e\f\x1cP"}, {"crypto/sha1", "\x0e\r+\x02,\x16\x16\x15T"},
{"crypto/sha3", "\x0e)O\xc9\x01"}, {"crypto/sha256", "\x0e\r\x1dR"},
{"crypto/sha512", "\x0e\f\x1eN"}, {"crypto/sha3", "\x0e+Q\xcb\x01"},
{"crypto/subtle", "\x1e\x1c\x9c\x01X"}, {"crypto/sha512", "\x0e\r\x1fP"},
{"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x02\x01\x01\t\x01\r\n\x01\n\x05\x03\x01\x01\x01\x01\x02\x01\x02\x01\x17\x02\x03\x12\x16\x15\b<\x16\x16\r\b\x01\x01\x01\x02\x01\r\x06\x02\x01\x0f"}, {"crypto/subtle", "\x1f\x1d\x9f\x01z"},
{"crypto/tls/internal/fips140tls", "\x17\xa5\x02"}, {"crypto/tls", "\x03\b\x02\x01\x01\x01\x01\x02\x01\x01\x01\x02\x01\x01\x01\t\x01\x18\x01\x0f\x01\x03\x01\x01\x01\x01\x02\x01\x02\x01\x17\x02\x03\x13\x16\x15\b=\x16\x16\r\b\x01\x01\x01\x02\x01\x0e\x06\x02\x01\x0f"},
{"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x015\x05\x01\x01\x02\x05\x0e\x06\x02\x02\x03E\x039\x01\x02\b\x01\x01\x02\a\x10\x05\x01\x06\x02\x05\b\x02\x01\x02\x0e\x02\x01\x01\x02\x03\x01"}, {"crypto/tls/internal/fips140tls", "\x17\xaa\x02"},
{"crypto/x509/pkix", "g\x06\a\x8e\x01G"}, {"crypto/x509", "\x03\v\x01\x01\x01\x01\x01\x01\x01\x017\x06\x01\x01\x02\x05\x0e\x06\x02\x02\x03F\x03:\x01\x02\b\x01\x01\x02\a\x10\x05\x01\x06\a\b\x02\x01\x02\x0f\x02\x01\x01\x02\x03\x01"},
{"database/sql", "\x03\nN\x16\x03\x81\x01\v\a\"\x05\b\x02\x03\x01\r\x02\x02\x02"}, {"crypto/x509/pkix", "j\x06\a\x90\x01H"},
{"database/sql/driver", "\rd\x03\xb5\x01\x0f\x11"}, {"database/sql", "\x03\nQ\x16\x03\x83\x01\v\a\"\x05\b\x02\x03\x01\x0e\x02\x02\x02"},
{"debug/buildinfo", "\x03[\x02\x01\x01\b\a\x03e\x1a\x02\x01+\x0f\x1f"}, {"database/sql/driver", "\rg\x03\xb7\x01\x0f\x12"},
{"debug/dwarf", "\x03g\a\x03\x81\x011\x11\x01\x01"}, {"debug/buildinfo", "\x03^\x02\x01\x01\b\a\x03g\x1a\x02\x01+\x0f "},
{"debug/elf", "\x03\x06T\r\a\x03e\x1b\x01\f \x17\x01\x16"}, {"debug/dwarf", "\x03j\a\x03\x83\x011\x11\x01\x01"},
{"debug/gosym", "\x03g\n\xc3\x01\x01\x01\x02"}, {"debug/elf", "\x03\x06W\r\a\x03g\x1b\x01\f \x17\x01\x17"},
{"debug/macho", "\x03\x06T\r\ne\x1c,\x17\x01"}, {"debug/gosym", "\x03j\n$\xa1\x01\x01\x01\x02"},
{"debug/pe", "\x03\x06T\r\a\x03e\x1c,\x17\x01\x16"}, {"debug/macho", "\x03\x06W\r\ng\x1c,\x17\x01"},
{"debug/plan9obj", "j\a\x03e\x1c,"}, {"debug/pe", "\x03\x06W\r\a\x03g\x1c,\x17\x01\x17"},
{"embed", "q*A\x19\x01S"}, {"debug/plan9obj", "m\a\x03g\x1c,"},
{"embed", "t+B\x19\x01T"},
{"embed/internal/embedtest", ""}, {"embed/internal/embedtest", ""},
{"encoding", ""}, {"encoding", ""},
{"encoding/ascii85", "\xf5\x01C"}, {"encoding/ascii85", "\xfa\x01C"},
{"encoding/asn1", "\x03n\x03e(\x01'\r\x02\x01\x10\x03\x01"}, {"encoding/asn1", "\x03q\x03g(\x01'\r\x02\x01\x11\x03\x01"},
{"encoding/base32", "\xf5\x01A\x02"}, {"encoding/base32", "\xfa\x01A\x02"},
{"encoding/base64", "\x9c\x01YA\x02"}, {"encoding/base64", "\xa0\x01ZA\x02"},
{"encoding/binary", "q\x84\x01\f(\r\x05"}, {"encoding/binary", "t\x86\x01\f(\r\x05"},
{"encoding/csv", "\x02\x01n\x03\x81\x01D\x12\x02"}, {"encoding/csv", "\x02\x01q\x03\x83\x01D\x13\x02"},
{"encoding/gob", "\x02c\x05\a\x03e\x1c\v\x01\x03\x1d\b\x12\x01\x0f\x02"}, {"encoding/gob", "\x02f\x05\a\x03g\x1c\v\x01\x03\x1d\b\x12\x01\x10\x02"},
{"encoding/hex", "q\x03\x81\x01A\x03"}, {"encoding/hex", "t\x03\x83\x01A\x03"},
{"encoding/json", "\x03\x01a\x04\b\x03\x81\x01\f(\r\x02\x01\x02\x10\x01\x01\x02"}, {"encoding/json", "\x03\x01d\x04\b\x03\x83\x01\f(\r\x02\x01\x02\x11\x01\x01\x02"},
{"encoding/pem", "\x03f\b\x84\x01A\x03"}, {"encoding/pem", "\x03i\b\x86\x01A\x03"},
{"encoding/xml", "\x02\x01b\f\x03\x81\x014\x05\n\x01\x02\x10\x02"}, {"encoding/xml", "\x02\x01e\f\x03\x83\x014\x05\n\x01\x02\x11\x02"},
{"errors", "\xcc\x01\x83\x01"}, {"errors", "\xd0\x01\x85\x01"},
{"expvar", "nK@\b\v\x15\r\b\x02\x03\x01\x11"}, {"expvar", "qLA\b\v\x15\r\b\x02\x03\x01\x12"},
{"flag", "e\f\x03\x81\x01,\b\x05\b\x02\x01\x10"}, {"flag", "h\f\x03\x83\x01,\b\x05\b\x02\x01\x11"},
{"fmt", "qE&\x19\f \b\r\x02\x03\x12"}, {"fmt", "tF'\x19\f \b\r\x02\x03\x13"},
{"go/ast", "\x03\x01p\x0e\x01r\x03)\b\r\x02\x01\x12\x02"}, {"go/ast", "\x03\x01s\x0f\x01s\x03)\b\r\x02\x01\x13\x02"},
{"go/build", "\x02\x01n\x03\x01\x02\x02\a\x02\x01\x17\x1f\x04\x02\b\x1b\x13\x01+\x01\x04\x01\a\b\x02\x01\x12\x02\x02"}, {"go/build", "\x02\x01q\x03\x01\x02\x02\b\x02\x01\x17\x1f\x04\x02\b\x1c\x13\x01+\x01\x04\x01\a\b\x02\x01\x13\x02\x02"},
{"go/build/constraint", "q\xc7\x01\x01\x12\x02"}, {"go/build/constraint", "t\xc9\x01\x01\x13\x02"},
{"go/constant", "t\x0f~\x01\x024\x01\x02\x12"}, {"go/constant", "w\x10\x7f\x01\x024\x01\x02\x13"},
{"go/doc", "\x04p\x01\x05\t=51\x10\x02\x01\x12\x02"}, {"go/doc", "\x04s\x01\x05\n=61\x10\x02\x01\x13\x02"},
{"go/doc/comment", "\x03q\xc2\x01\x01\x01\x01\x12\x02"}, {"go/doc/comment", "\x03t\xc4\x01\x01\x01\x01\x13\x02"},
{"go/format", "\x03q\x01\v\x01\x02rD"}, {"go/format", "\x03t\x01\f\x01\x02sD"},
{"go/importer", "v\a\x01\x01\x04\x01q9"}, {"go/importer", "y\a\x01\x02\x04\x01r9"},
{"go/internal/gccgoimporter", "\x02\x01[\x13\x03\x04\v\x01o\x02,\x01\x05\x11\x01\f\b"}, {"go/internal/gccgoimporter", "\x02\x01^\x13\x03\x04\f\x01p\x02,\x01\x05\x11\x01\r\b"},
{"go/internal/gcimporter", "\x02r\x0f\x010\x05\r/,\x15\x03\x02"}, {"go/internal/gcimporter", "\x02u\x10\x010\x05\r0,\x15\x03\x02"},
{"go/internal/srcimporter", "t\x01\x01\n\x03\x01q,\x01\x05\x12\x02\x14"}, {"go/internal/scannerhooks", "\x87\x01"},
{"go/parser", "\x03n\x03\x01\x02\v\x01r\x01+\x06\x12"}, {"go/internal/srcimporter", "w\x01\x01\v\x03\x01r,\x01\x05\x12\x02\x15"},
{"go/printer", "t\x01\x02\x03\tr\f \x15\x02\x01\x02\v\x05\x02"}, {"go/parser", "\x03q\x03\x01\x02\b\x04\x01s\x01+\x06\x12"},
{"go/scanner", "\x03q\x0fr2\x10\x01\x13\x02"}, {"go/printer", "w\x01\x02\x03\ns\f \x15\x02\x01\x02\f\x05\x02"},
{"go/token", "\x04p\x84\x01>\x02\x03\x01\x0f\x02"}, {"go/scanner", "\x03t\v\x05s2\x10\x01\x14\x02"},
{"go/types", "\x03\x01\x06g\x03\x01\x03\b\x03\x024\x062\x04\x03\t \x06\a\b\x01\x01\x01\x02\x01\x0f\x02\x02"}, {"go/token", "\x04s\x86\x01>\x02\x03\x01\x10\x02"},
{"go/version", "\xbe\x01{"}, {"go/types", "\x03\x01\x06j\x03\x01\x03\t\x03\x024\x063\x04\x03\t \x06\a\b\x01\x01\x01\x02\x01\x10\x02\x02"},
{"hash", "\xf5\x01"}, {"go/version", "\xc2\x01|"},
{"hash/adler32", "q\x15\x16"}, {"hash", "\xfa\x01"},
{"hash/crc32", "q\x15\x16\x15\x8a\x01\x01\x13"}, {"hash/adler32", "t\x16\x16"},
{"hash/crc64", "q\x15\x16\x9f\x01"}, {"hash/crc32", "t\x16\x16\x15\x8b\x01\x01\x14"},
{"hash/fnv", "q\x15\x16h"}, {"hash/crc64", "t\x16\x16\xa0\x01"},
{"hash/maphash", "\x86\x01\x11<|"}, {"hash/fnv", "t\x16\x16i"},
{"html", "\xb9\x02\x02\x12"}, {"hash/maphash", "\x8a\x01\x11<~"},
{"html/template", "\x03k\x06\x18-<\x01\n!\x05\x01\x02\x03\f\x01\x02\f\x01\x03\x02"}, {"html", "\xbe\x02\x02\x13"},
{"image", "\x02o\x1ef\x0f4\x03\x01"}, {"html/template", "\x03n\x06\x19-=\x01\n!\x05\x01\x02\x03\f\x01\x02\r\x01\x03\x02"},
{"image", "\x02r\x1fg\x0f4\x03\x01"},
{"image/color", ""}, {"image/color", ""},
{"image/color/palette", "\x8f\x01"}, {"image/color/palette", "\x93\x01"},
{"image/draw", "\x8e\x01\x01\x04"}, {"image/draw", "\x92\x01\x01\x04"},
{"image/gif", "\x02\x01\x05i\x03\x1a\x01\x01\x01\vY"}, {"image/gif", "\x02\x01\x05l\x03\x1b\x01\x01\x01\vZ\x0f"},
{"image/internal/imageutil", "\x8e\x01"}, {"image/internal/imageutil", "\x92\x01"},
{"image/jpeg", "\x02o\x1d\x01\x04b"}, {"image/jpeg", "\x02r\x1e\x01\x04c"},
{"image/png", "\x02\aa\n\x12\x02\x06\x01fC"}, {"image/png", "\x02\ad\n\x13\x02\x06\x01gC"},
{"index/suffixarray", "\x03g\a\x84\x01\f+\n\x01"}, {"index/suffixarray", "\x03j\a\x86\x01\f+\n\x01"},
{"internal/abi", "\xb8\x01\x97\x01"}, {"internal/abi", "\xbc\x01\x99\x01"},
{"internal/asan", "\xcf\x02"}, {"internal/asan", "\xd5\x02"},
{"internal/bisect", "\xae\x02\r\x01"}, {"internal/bisect", "\xb3\x02\r\x01"},
{"internal/buildcfg", "tGf\x06\x02\x05\n\x01"}, {"internal/buildcfg", "wHg\x06\x02\x05\n\x01"},
{"internal/bytealg", "\xb1\x01\x9e\x01"}, {"internal/bytealg", "\xb5\x01\xa0\x01"},
{"internal/byteorder", ""}, {"internal/byteorder", ""},
{"internal/cfg", ""}, {"internal/cfg", ""},
{"internal/cgrouptest", "tZS\x06\x0f\x02\x01\x04\x01"}, {"internal/cgrouptest", "w[T\x06\x0f\x02\x01\x04\x01"},
{"internal/chacha8rand", "\x9c\x01\x15\a\x97\x01"}, {"internal/chacha8rand", "\xa0\x01\x15\a\x99\x01"},
{"internal/copyright", ""}, {"internal/copyright", ""},
{"internal/coverage", ""}, {"internal/coverage", ""},
{"internal/coverage/calloc", ""}, {"internal/coverage/calloc", ""},
{"internal/coverage/cfile", "n\x06\x16\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01\"\x02&,\x06\a\n\x01\x03\r\x06"}, {"internal/coverage/cfile", "q\x06\x17\x17\x01\x02\x01\x01\x01\x01\x01\x01\x01\"\x02',\x06\a\n\x01\x03\x0e\x06"},
{"internal/coverage/cformat", "\x04p-\x04P\v6\x01\x02\r"}, {"internal/coverage/cformat", "\x04s.\x04Q\v6\x01\x02\x0e"},
{"internal/coverage/cmerge", "t-`"}, {"internal/coverage/cmerge", "w.a"},
{"internal/coverage/decodecounter", "j\n-\v\x02G,\x17\x17"}, {"internal/coverage/decodecounter", "m\n.\v\x02H,\x17\x18"},
{"internal/coverage/decodemeta", "\x02h\n\x16\x17\v\x02G,"}, {"internal/coverage/decodemeta", "\x02k\n\x17\x17\v\x02H,"},
{"internal/coverage/encodecounter", "\x02h\n-\f\x01\x02E\v!\x15"}, {"internal/coverage/encodecounter", "\x02k\n.\f\x01\x02F\v!\x15"},
{"internal/coverage/encodemeta", "\x02\x01g\n\x12\x04\x17\r\x02E,."}, {"internal/coverage/encodemeta", "\x02\x01j\n\x13\x04\x17\r\x02F,/"},
{"internal/coverage/pods", "\x04p-\x80\x01\x06\x05\n\x02\x01"}, {"internal/coverage/pods", "\x04s.\x81\x01\x06\x05\n\x02\x01"},
{"internal/coverage/rtcov", "\xcf\x02"}, {"internal/coverage/rtcov", "\xd5\x02"},
{"internal/coverage/slicereader", "j\n\x81\x01Z"}, {"internal/coverage/slicereader", "m\n\x83\x01["},
{"internal/coverage/slicewriter", "t\x81\x01"}, {"internal/coverage/slicewriter", "w\x83\x01"},
{"internal/coverage/stringtab", "t8\x04E"}, {"internal/coverage/stringtab", "w9\x04F"},
{"internal/coverage/test", ""}, {"internal/coverage/test", ""},
{"internal/coverage/uleb128", ""}, {"internal/coverage/uleb128", ""},
{"internal/cpu", "\xcf\x02"}, {"internal/cpu", "\xd5\x02"},
{"internal/dag", "\x04p\xc2\x01\x03"}, {"internal/dag", "\x04s\xc4\x01\x03"},
{"internal/diff", "\x03q\xc3\x01\x02"}, {"internal/diff", "\x03t\xc5\x01\x02"},
{"internal/exportdata", "\x02\x01n\x03\x02c\x1c,\x01\x05\x11\x01\x02"}, {"internal/exportdata", "\x02\x01q\x03\x02e\x1c,\x01\x05\x11\x01\x02"},
{"internal/filepathlite", "q*A\x1a@"}, {"internal/filepathlite", "t+B\x1a@"},
{"internal/fmtsort", "\x04\xa5\x02\r"}, {"internal/fmtsort", "\x04\xaa\x02\r"},
{"internal/fuzz", "\x03\nE\x18\x04\x03\x03\x01\v\x036<\f\x03\x1d\x01\x05\x02\x05\n\x01\x02\x01\x01\f\x04\x02"}, {"internal/fuzz", "\x03\nH\x18\x04\x03\x03\x01\f\x036=\f\x03\x1d\x01\x05\x02\x05\n\x01\x02\x01\x01\r\x04\x02"},
{"internal/goarch", ""}, {"internal/goarch", ""},
{"internal/godebug", "\x99\x01!\x81\x01\x01\x13"}, {"internal/godebug", "\x9d\x01!\x82\x01\x01\x14"},
{"internal/godebugs", ""}, {"internal/godebugs", ""},
{"internal/goexperiment", ""}, {"internal/goexperiment", ""},
{"internal/goos", ""}, {"internal/goos", ""},
{"internal/goroot", "\xa1\x02\x01\x05\x12\x02"}, {"internal/goroot", "\xa6\x02\x01\x05\x12\x02"},
{"internal/gover", "\x04"}, {"internal/gover", "\x04"},
{"internal/goversion", ""}, {"internal/goversion", ""},
{"internal/lazyregexp", "\xa1\x02\v\r\x02"}, {"internal/lazyregexp", "\xa6\x02\v\r\x02"},
{"internal/lazytemplate", "\xf5\x01,\x18\x02\f"}, {"internal/lazytemplate", "\xfa\x01,\x18\x02\r"},
{"internal/msan", "\xcf\x02"}, {"internal/msan", "\xd5\x02"},
{"internal/nettrace", ""}, {"internal/nettrace", ""},
{"internal/obscuretestdata", "i\x8c\x01,"}, {"internal/obscuretestdata", "l\x8e\x01,"},
{"internal/oserror", "q"}, {"internal/oserror", "t"},
{"internal/pkgbits", "\x03O\x18\a\x03\x04\vr\r\x1f\r\n\x01"}, {"internal/pkgbits", "\x03R\x18\a\x03\x04\fs\r\x1f\r\n\x01"},
{"internal/platform", ""}, {"internal/platform", ""},
{"internal/poll", "qj\x05\x159\r\x01\x01\f\x06"}, {"internal/poll", "tl\x05\x159\r\x01\x01\r\x06"},
{"internal/profile", "\x03\x04j\x03\x81\x017\n\x01\x01\x01\x10"}, {"internal/profile", "\x03\x04m\x03\x83\x017\n\x01\x01\x01\x11"},
{"internal/profilerecord", ""}, {"internal/profilerecord", ""},
{"internal/race", "\x97\x01\xb8\x01"}, {"internal/race", "\x9b\x01\xba\x01"},
{"internal/reflectlite", "\x97\x01!:<!"}, {"internal/reflectlite", "\x9b\x01!;<\""},
{"internal/runtime/atomic", "\xb8\x01\x97\x01"}, {"internal/runtime/atomic", "\xbc\x01\x99\x01"},
{"internal/runtime/cgroup", "\x9b\x01<\x04t"}, {"internal/runtime/cgroup", "\x9f\x01=\x04u"},
{"internal/runtime/exithook", "\xcd\x01\x82\x01"}, {"internal/runtime/exithook", "\xd1\x01\x84\x01"},
{"internal/runtime/gc", "\xb8\x01"}, {"internal/runtime/gc", "\xbc\x01"},
{"internal/runtime/gc/internal/gen", "\n`\n\x17j\x04\v\x1d\b\x10\x02"}, {"internal/runtime/gc/internal/gen", "\nc\n\x18k\x04\v\x1d\b\x10\x02"},
{"internal/runtime/gc/scan", "\xb1\x01\a\x18\x06y"}, {"internal/runtime/gc/scan", "\xb5\x01\a\x18\az"},
{"internal/runtime/maps", "\x97\x01\x01 \n\t\t\x02y"}, {"internal/runtime/maps", "\x9b\x01\x01 \n\t\t\x03z"},
{"internal/runtime/math", "\xb8\x01"}, {"internal/runtime/math", "\xbc\x01"},
{"internal/runtime/pprof/label", ""},
{"internal/runtime/startlinetest", ""}, {"internal/runtime/startlinetest", ""},
{"internal/runtime/sys", "\xb8\x01\x04"}, {"internal/runtime/sys", "\xbc\x01\x04"},
{"internal/runtime/syscall/linux", "\xb8\x01\x97\x01"}, {"internal/runtime/syscall/linux", "\xbc\x01\x99\x01"},
{"internal/runtime/wasitest", ""}, {"internal/runtime/wasitest", ""},
{"internal/saferio", "\xf5\x01Z"}, {"internal/saferio", "\xfa\x01["},
{"internal/singleflight", "\xbb\x02"}, {"internal/singleflight", "\xc0\x02"},
{"internal/strconv", "\x84\x02K"}, {"internal/strconv", "\x89\x02L"},
{"internal/stringslite", "\x9b\x01\xb4\x01"}, {"internal/stringslite", "\x9f\x01\xb6\x01"},
{"internal/sync", "\x97\x01!\x13q\x13"}, {"internal/sync", "\x9b\x01!\x13r\x14"},
{"internal/synctest", "\x97\x01\xb8\x01"}, {"internal/synctest", "\x9b\x01\xba\x01"},
{"internal/syscall/execenv", "\xbd\x02"}, {"internal/syscall/execenv", "\xc2\x02"},
{"internal/syscall/unix", "\xae\x02\x0e\x01\x12"}, {"internal/syscall/unix", "\xb3\x02\x0e\x01\x13"},
{"internal/sysinfo", "\x02\x01\xae\x01D,\x18\x02"}, {"internal/sysinfo", "\x02\x01\xb2\x01E,\x18\x02"},
{"internal/syslist", ""}, {"internal/syslist", ""},
{"internal/testenv", "\x03\nd\x02\x01)\x1b\x0f/+\x01\x05\a\n\x01\x02\x02\x01\v"}, {"internal/testenv", "\x03\ng\x02\x01*\x1b\x0f0+\x01\x05\a\n\x01\x02\x02\x01\f"},
{"internal/testhash", "\x03\x83\x01o\x118\v"}, {"internal/testhash", "\x03\x87\x01p\x118\f"},
{"internal/testlog", "\xbb\x02\x01\x13"}, {"internal/testlog", "\xc0\x02\x01\x14"},
{"internal/testpty", "q\x03\xad\x01"}, {"internal/testpty", "t\x03\xaf\x01"},
{"internal/trace", "\x02\x01\x01\x06`\a\x03u\x03\x03\x06\x03\t5\x01\x01\x01\x10\x06"}, {"internal/trace", "\x02\x01\x01\x06c\a\x03w\x03\x03\x06\x03\t+\n\x01\x01\x01\x11\x06"},
{"internal/trace/internal/testgen", "\x03g\ns\x03\x02\x03\x011\v\r\x10"}, {"internal/trace/internal/testgen", "\x03j\nu\x03\x02\x03\x011\v\r\x11"},
{"internal/trace/internal/tracev1", "\x03\x01f\a\x03{\x06\f5\x01"}, {"internal/trace/internal/tracev1", "\x03\x01i\a\x03}\x06\f5\x01"},
{"internal/trace/raw", "\x02h\nx\x03\x06C\x01\x12"}, {"internal/trace/raw", "\x02k\nz\x03\x06C\x01\x13"},
{"internal/trace/testtrace", "\x02\x01n\x03o\x04\x03\x05\x01\x05,\v\x02\b\x02\x01\x05"}, {"internal/trace/testtrace", "\x02\x01q\x03q\x04\x03\x05\x01\x05,\v\x02\b\x02\x01\x05"},
{"internal/trace/tracev2", ""}, {"internal/trace/tracev2", ""},
{"internal/trace/traceviewer", "\x02a\v\x06\x19<\x1e\a\a\x04\b\v\x15\x01\x05\a\n\x01\x02\x0e"}, {"internal/trace/traceviewer", "\x02d\v\x06\x1a<\x1f\a\a\x04\b\v\x15\x01\x05\a\n\x01\x02\x0f"},
{"internal/trace/traceviewer/format", ""}, {"internal/trace/traceviewer/format", ""},
{"internal/trace/version", "tx\t"}, {"internal/trace/version", "wz\t"},
{"internal/txtar", "\x03q\xad\x01\x18"}, {"internal/txtar", "\x03t\xaf\x01\x18"},
{"internal/types/errors", "\xb8\x02"}, {"internal/types/errors", "\xbd\x02"},
{"internal/unsafeheader", "\xcf\x02"}, {"internal/unsafeheader", "\xd5\x02"},
{"internal/xcoff", "]\r\a\x03e\x1c,\x17\x01"}, {"internal/xcoff", "`\r\a\x03g\x1c,\x17\x01"},
{"internal/zstd", "j\a\x03\x81\x01\x0f"}, {"internal/zstd", "m\a\x03\x83\x01\x0f"},
{"io", "q\xca\x01"}, {"io", "t\xcc\x01"},
{"io/fs", "q**01\x10\x13\x04"}, {"io/fs", "t+*11\x10\x14\x04"},
{"io/ioutil", "\xf5\x01\x01+\x15\x03"}, {"io/ioutil", "\xfa\x01\x01+\x15\x03"},
{"iter", "\xcb\x01c!"}, {"iter", "\xcf\x01d\""},
{"log", "t\x81\x01\x05'\r\r\x01\r"}, {"log", "w\x83\x01\x05'\r\r\x01\x0e"},
{"log/internal", ""}, {"log/internal", ""},
{"log/slog", "\x03\nX\t\x03\x03\x81\x01\x04\x01\x02\x02\x03(\x05\b\x02\x01\x02\x01\r\x02\x02\x02"}, {"log/slog", "\x03\n[\t\x03\x03\x83\x01\x04\x01\x02\x02\x03(\x05\b\x02\x01\x02\x01\x0e\x02\x02\x02"},
{"log/slog/internal", ""}, {"log/slog/internal", ""},
{"log/slog/internal/benchmarks", "\rd\x03\x81\x01\x06\x03:\x11"}, {"log/slog/internal/benchmarks", "\rg\x03\x83\x01\x06\x03:\x12"},
{"log/slog/internal/buffer", "\xbb\x02"}, {"log/slog/internal/buffer", "\xc0\x02"},
{"log/syslog", "q\x03\x85\x01\x12\x16\x18\x02\x0e"}, {"log/syslog", "t\x03\x87\x01\x12\x16\x18\x02\x0f"},
{"maps", "\xf8\x01W"}, {"maps", "\xfd\x01X"},
{"math", "\xb1\x01SK"}, {"math", "\xb5\x01TL"},
{"math/big", "\x03n\x03(\x15D\f\x03\x020\x02\x01\x02\x14"}, {"math/big", "\x03q\x03)\x15E\f\x03\x020\x02\x01\x02\x15"},
{"math/big/internal/asmgen", "\x03\x01p\x90\x012\x03"}, {"math/big/internal/asmgen", "\x03\x01s\x92\x012\x03"},
{"math/bits", "\xcf\x02"}, {"math/bits", "\xd5\x02"},
{"math/cmplx", "\x81\x02\x03"}, {"math/cmplx", "\x86\x02\x03"},
{"math/rand", "\xb9\x01H:\x01\x13"}, {"math/rand", "\xbd\x01I:\x01\x14"},
{"math/rand/v2", "q+\x03b\x03K"}, {"math/rand/v2", "t,\x03c\x03L"},
{"mime", "\x02\x01f\b\x03\x81\x01\v!\x15\x03\x02\x10\x02"}, {"mime", "\x02\x01i\b\x03\x83\x01\v!\x15\x03\x02\x11\x02"},
{"mime/multipart", "\x02\x01K#\x03E<\v\x01\a\x02\x15\x02\x06\x0f\x02\x01\x16"}, {"mime/multipart", "\x02\x01N#\x03F=\v\x01\a\x02\x15\x02\x06\x0f\x02\x01\x17"},
{"mime/quotedprintable", "\x02\x01q\x81\x01"}, {"mime/quotedprintable", "\x02\x01t\x83\x01"},
{"net", "\x04\td*\x1e\n\x05\x12\x01\x01\x04\x15\x01%\x06\r\b\x05\x01\x01\f\x06\a"}, {"net", "\x04\tg+\x1e\n\x05\x13\x01\x01\x04\x15\x01%\x06\r\b\x05\x01\x01\r\x06\a"},
{"net/http", "\x02\x01\x03\x01\x04\x02A\b\x13\x01\a\x03E<\x01\x03\a\x01\x03\x02\x02\x01\x02\x06\x02\x01\x01\n\x01\x01\x05\x01\x02\x05\b\x01\x01\x01\x02\x01\r\x02\x02\x02\b\x01\x01\x01"}, {"net/http", "\x02\x01\x03\x01\x04\x02D\b\x13\x01\a\x03F=\x01\x03\a\x01\x03\x02\x02\x01\x02\x06\x02\x01\x01\n\x01\x01\x05\x01\x02\x05\b\x01\x01\x01\x02\x01\x0e\x02\x02\x02\b\x01\x01\x01"},
{"net/http/cgi", "\x02T\x1b\x03\x81\x01\x04\a\v\x01\x13\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x10\x0e"}, {"net/http/cgi", "\x02W\x1b\x03\x83\x01\x04\a\v\x01\x13\x01\x01\x01\x04\x01\x05\x02\b\x02\x01\x11\x0e"},
{"net/http/cookiejar", "\x04m\x03\x97\x01\x01\b\f\x16\x03\x02\x0e\x04"}, {"net/http/cookiejar", "\x04p\x03\x99\x01\x01\b\a\x05\x16\x03\x02\x0f\x04"},
{"net/http/fcgi", "\x02\x01\n]\a\x03\x81\x01\x16\x01\x01\x14\x18\x02\x0e"}, {"net/http/fcgi", "\x02\x01\n`\a\x03\x83\x01\x16\x01\x01\x14\x18\x02\x0f"},
{"net/http/httptest", "\x02\x01\nI\x02\x1b\x01\x81\x01\x04\x12\x01\n\t\x02\x17\x01\x02\x0e\x0e"}, {"net/http/httptest", "\x02\x01\nL\x02\x1b\x01\x83\x01\x04\x12\x01\n\t\x02\x17\x01\x02\x0f\x0e"},
{"net/http/httptrace", "\rImH\x14\n "}, {"net/http/httptrace", "\rLnI\x14\n!"},
{"net/http/httputil", "\x02\x01\nd\x03\x81\x01\x04\x0f\x03\x01\x05\x02\x01\v\x01\x19\x02\x0e\x0e"}, {"net/http/httputil", "\x02\x01\ng\x03\x83\x01\x04\x0f\x03\x01\x05\x02\x01\v\x01\x19\x02\x01\x0e\x0e"},
{"net/http/internal", "\x02\x01n\x03\x81\x01"}, {"net/http/internal", "\x02\x01q\x03\x83\x01"},
{"net/http/internal/ascii", "\xb9\x02\x12"}, {"net/http/internal/ascii", "\xbe\x02\x13"},
{"net/http/internal/httpcommon", "\rd\x03\x9d\x01\x0e\x01\x17\x01\x01\x02\x1c\x02"}, {"net/http/internal/httpcommon", "\rg\x03\x9f\x01\x0e\x01\x17\x01\x01\x02\x1d\x02"},
{"net/http/internal/testcert", "\xb9\x02"}, {"net/http/internal/testcert", "\xbe\x02"},
{"net/http/pprof", "\x02\x01\ng\x18-\x02\x0e,\x04\x13\x14\x01\r\x04\x03\x01\x02\x01\x10"}, {"net/http/pprof", "\x02\x01\nj\x19-\x02\x0e-\x04\x13\x14\x01\r\x04\x03\x01\x02\x01\x11"},
{"net/internal/cgotest", ""}, {"net/internal/cgotest", ""},
{"net/internal/socktest", "t\xc7\x01\x02"}, {"net/internal/socktest", "w\xc9\x01\x02"},
{"net/mail", "\x02o\x03\x81\x01\x04\x0f\x03\x14\x1a\x02\x0e\x04"}, {"net/mail", "\x02r\x03\x83\x01\x04\x0f\x03\x14\x1a\x02\x0f\x04"},
{"net/netip", "\x04m*\x01e\x034\x16"}, {"net/netip", "\x04p+\x01f\x034\x17"},
{"net/rpc", "\x02j\x05\x03\x0f\nh\x04\x12\x01\x1d\r\x03\x02"}, {"net/rpc", "\x02m\x05\x03\x10\ni\x04\x12\x01\x1d\r\x03\x02"},
{"net/rpc/jsonrpc", "n\x03\x03\x81\x01\x16\x11\x1f"}, {"net/rpc/jsonrpc", "q\x03\x03\x83\x01\x16\x11\x1f"},
{"net/smtp", "\x192\v\x13\b\x03\x81\x01\x16\x14\x1a"}, {"net/smtp", "\x194\f\x13\b\x03\x83\x01\x16\x14\x1a"},
{"net/textproto", "\x02\x01n\x03\x81\x01\f\n-\x01\x02\x14"}, {"net/textproto", "\x02\x01q\x03\x83\x01\f\n-\x01\x02\x15"},
{"net/url", "q\x03\xa7\x01\v\x10\x02\x01\x16"}, {"net/url", "t\x03Fc\v\x10\x02\x01\x17"},
{"os", "q*\x01\x19\x03\x10\x13\x01\x03\x01\x05\x10\x018\b\x05\x01\x01\f\x06"}, {"os", "t+\x01\x19\x03\x10\x14\x01\x03\x01\x05\x10\x018\b\x05\x01\x01\r\x06"},
{"os/exec", "\x03\ndH&\x01\x15\x01+\x06\a\n\x01\x04\f"}, {"os/exec", "\x03\ngI'\x01\x15\x01+\x06\a\n\x01\x03\x01\r"},
{"os/exec/internal/fdtest", "\xbd\x02"}, {"os/exec/internal/fdtest", "\xc2\x02"},
{"os/signal", "\r\x94\x02\x15\x05\x02"}, {"os/signal", "\r\x99\x02\x15\x05\x02"},
{"os/user", "\x02\x01n\x03\x81\x01,\r\n\x01\x02"}, {"os/user", "\x02\x01q\x03\x83\x01,\r\n\x01\x02"},
{"path", "q*\xb2\x01"}, {"path", "t+\xb4\x01"},
{"path/filepath", "q*\x1aA+\r\b\x03\x04\x10"}, {"path/filepath", "t+\x1aB+\r\b\x03\x04\x11"},
{"plugin", "q"}, {"plugin", "t"},
{"reflect", "q&\x04\x1d\x13\b\x03\x05\x17\x06\t-\n\x03\x10\x02\x02"}, {"reflect", "t'\x04\x1d\x13\b\x04\x05\x17\x06\t-\n\x03\x11\x02\x02"},
{"reflect/internal/example1", ""}, {"reflect/internal/example1", ""},
{"reflect/internal/example2", ""}, {"reflect/internal/example2", ""},
{"regexp", "\x03\xf2\x018\t\x02\x01\x02\x10\x02"}, {"regexp", "\x03\xf7\x018\t\x02\x01\x02\x11\x02"},
{"regexp/syntax", "\xb6\x02\x01\x01\x01\x02\x10\x02"}, {"regexp/syntax", "\xbb\x02\x01\x01\x01\x02\x11\x02"},
{"runtime", "\x97\x01\x04\x01\x03\f\x06\a\x02\x01\x01\x0e\x03\x01\x01\x01\x02\x01\x01\x02\x01\x04\x01\x10c"}, {"runtime", "\x9b\x01\x04\x01\x03\f\x06\a\x02\x01\x01\x0e\x03\x01\x01\x01\x02\x01\x01\x01\x02\x01\x04\x01\x10\x18L"},
{"runtime/coverage", "\xa3\x01R"}, {"runtime/coverage", "\xa7\x01S"},
{"runtime/debug", "tTY\r\b\x02\x01\x10\x06"}, {"runtime/debug", "wUZ\r\b\x02\x01\x11\x06"},
{"runtime/metrics", "\xba\x01G-!"}, {"runtime/metrics", "\xbe\x01H-\""},
{"runtime/pprof", "\x02\x01\x01\x03\x06]\a\x03#$\x0f+\f \r\b\x01\x01\x01\x02\x02\t\x03\x06"}, {"runtime/pprof", "\x02\x01\x01\x03\x06`\a\x03$$\x0f\v!\f \r\b\x01\x01\x01\x02\x02\n\x03\x06"},
{"runtime/race", "\xb4\x02"}, {"runtime/race", "\xb9\x02"},
{"runtime/race/internal/amd64v1", ""}, {"runtime/race/internal/amd64v1", ""},
{"runtime/trace", "\rd\x03x\t9\b\x05\x01\r\x06"}, {"runtime/trace", "\rg\x03z\t9\b\x05\x01\x0e\x06"},
{"slices", "\x04\xf4\x01\fK"}, {"slices", "\x04\xf9\x01\fL"},
{"sort", "\xcc\x0182"}, {"sort", "\xd0\x0192"},
{"strconv", "q*@\x01q"}, {"strconv", "t+A\x01r"},
{"strings", "q&\x04A\x19\x03\f7\x10\x02\x02"}, {"strings", "t'\x04B\x19\x03\f7\x11\x02\x02"},
{"structs", ""}, {"structs", ""},
{"sync", "\xcb\x01\x12\x01P\x0e\x13"}, {"sync", "\xcf\x01\x13\x01P\x0e\x14"},
{"sync/atomic", "\xcf\x02"}, {"sync/atomic", "\xd5\x02"},
{"syscall", "q'\x03\x01\x1c\n\x03\x06\f\x04S\b\x05\x01\x13"}, {"syscall", "t(\x03\x01\x1c\n\x03\x06\r\x04S\b\x05\x01\x14"},
{"testing", "\x03\nd\x02\x01W\x16\x14\f\x05\x1b\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\r\x02\x04"}, {"testing", "\x03\ng\x02\x01X\x17\x14\f\x05\x1b\x06\x02\x05\x02\x05\x01\x02\x01\x02\x01\x0e\x02\x04"},
{"testing/fstest", "q\x03\x81\x01\x01\n&\x10\x03\b\b"}, {"testing/cryptotest", "QOZ\x124\x03\x12"},
{"testing/internal/testdeps", "\x02\v\xaa\x01.\x10,\x03\x05\x03\x06\a\x02\x0e"}, {"testing/fstest", "t\x03\x83\x01\x01\n&\x10\x03\t\b"},
{"testing/iotest", "\x03n\x03\x81\x01\x04"}, {"testing/internal/testdeps", "\x02\v\xae\x01/\x10,\x03\x05\x03\x06\a\x02\x0f"},
{"testing/quick", "s\x01\x8d\x01\x05#\x10\x10"}, {"testing/iotest", "\x03q\x03\x83\x01\x04"},
{"testing/slogtest", "\rd\x03\x87\x01.\x05\x10\v"}, {"testing/quick", "v\x01\x8f\x01\x05#\x10\x11"},
{"testing/synctest", "\xde\x01`\x11"}, {"testing/slogtest", "\rg\x03\x89\x01.\x05\x10\f"},
{"text/scanner", "\x03q\x81\x01,*\x02"}, {"testing/synctest", "\xe3\x01`\x12"},
{"text/tabwriter", "t\x81\x01X"}, {"text/scanner", "\x03t\x83\x01,+\x02"},
{"text/template", "q\x03B?\x01\n \x01\x05\x01\x02\x05\v\x02\r\x03\x02"}, {"text/tabwriter", "w\x83\x01Y"},
{"text/template/parse", "\x03q\xba\x01\n\x01\x12\x02"}, {"text/template", "t\x03C@\x01\n \x01\x05\x01\x02\x05\v\x02\x0e\x03\x02"},
{"time", "q*\x1e#(*\r\x02\x12"}, {"text/template/parse", "\x03t\xbc\x01\n\x01\x13\x02"},
{"time/tzdata", "q\xcc\x01\x12"}, {"time", "t+\x1e$(*\r\x02\x13"},
{"time/tzdata", "t\xce\x01\x13"},
{"unicode", ""}, {"unicode", ""},
{"unicode/utf16", ""}, {"unicode/utf16", ""},
{"unicode/utf8", ""}, {"unicode/utf8", ""},
{"unique", "\x97\x01!$\x01Q\r\x01\x13\x12"}, {"unique", "\x9b\x01!%\x01Q\r\x01\x14\x12"},
{"unsafe", ""}, {"unsafe", ""},
{"vendor/golang.org/x/crypto/chacha20", "\x10Z\a\x93\x01*&"}, {"vendor/golang.org/x/crypto/chacha20", "\x10]\a\x95\x01*'"},
{"vendor/golang.org/x/crypto/chacha20poly1305", "\x10Z\a\xdf\x01\x04\x01\a"}, {"vendor/golang.org/x/crypto/chacha20poly1305", "\x10\aV\a\xe2\x01\x04\x01\a"},
{"vendor/golang.org/x/crypto/cryptobyte", "g\n\x03\x8e\x01' \n"}, {"vendor/golang.org/x/crypto/cryptobyte", "j\n\x03\x90\x01'!\n"},
{"vendor/golang.org/x/crypto/cryptobyte/asn1", ""}, {"vendor/golang.org/x/crypto/cryptobyte/asn1", ""},
{"vendor/golang.org/x/crypto/internal/alias", "\xcf\x02"}, {"vendor/golang.org/x/crypto/internal/alias", "\xd5\x02"},
{"vendor/golang.org/x/crypto/internal/poly1305", "U\x15\x9a\x01"}, {"vendor/golang.org/x/crypto/internal/poly1305", "X\x15\x9c\x01"},
{"vendor/golang.org/x/net/dns/dnsmessage", "q"}, {"vendor/golang.org/x/net/dns/dnsmessage", "t\xc7\x01"},
{"vendor/golang.org/x/net/http/httpguts", "\x8b\x02\x14\x1a\x14\r"}, {"vendor/golang.org/x/net/http/httpguts", "\x90\x02\x14\x1a\x15\r"},
{"vendor/golang.org/x/net/http/httpproxy", "q\x03\x97\x01\x10\x05\x01\x18\x14\r"}, {"vendor/golang.org/x/net/http/httpproxy", "t\x03\x99\x01\x10\x05\x01\x18\x15\r"},
{"vendor/golang.org/x/net/http2/hpack", "\x03n\x03\x81\x01F"}, {"vendor/golang.org/x/net/http2/hpack", "\x03q\x03\x83\x01F"},
{"vendor/golang.org/x/net/idna", "t\x8d\x018\x14\x10\x02\x01"}, {"vendor/golang.org/x/net/idna", "w\x8f\x018\x15\x10\x02\x01"},
{"vendor/golang.org/x/net/nettest", "\x03g\a\x03\x81\x01\x11\x05\x16\x01\f\n\x01\x02\x02\x01\v"}, {"vendor/golang.org/x/net/nettest", "\x03j\a\x03\x83\x01\x11\x05\x16\x01\f\n\x01\x02\x02\x01\f"},
{"vendor/golang.org/x/sys/cpu", "\xa1\x02\r\n\x01\x16"}, {"vendor/golang.org/x/sys/cpu", "\xa6\x02\r\n\x01\x17"},
{"vendor/golang.org/x/text/secure/bidirule", "q\xdc\x01\x11\x01"}, {"vendor/golang.org/x/text/secure/bidirule", "t\xdf\x01\x11\x01"},
{"vendor/golang.org/x/text/transform", "\x03n\x84\x01X"}, {"vendor/golang.org/x/text/transform", "\x03q\x86\x01Y"},
{"vendor/golang.org/x/text/unicode/bidi", "\x03\bi\x85\x01>\x16"}, {"vendor/golang.org/x/text/unicode/bidi", "\x03\bl\x87\x01>\x17"},
{"vendor/golang.org/x/text/unicode/norm", "j\n\x81\x01F\x12\x11"}, {"vendor/golang.org/x/text/unicode/norm", "m\n\x83\x01F\x13\x11"},
{"weak", "\x97\x01\x97\x01!"}, {"weak", "\x9b\x01\x98\x01\""},
} }
// bootstrap is the list of bootstrap packages extracted from cmd/dist. // bootstrap is the list of bootstrap packages extracted from cmd/dist.
@ -385,6 +391,7 @@ var bootstrap = map[string]bool{
"cmd/compile/internal/arm64": true, "cmd/compile/internal/arm64": true,
"cmd/compile/internal/base": true, "cmd/compile/internal/base": true,
"cmd/compile/internal/bitvec": true, "cmd/compile/internal/bitvec": true,
"cmd/compile/internal/bloop": true,
"cmd/compile/internal/compare": true, "cmd/compile/internal/compare": true,
"cmd/compile/internal/coverage": true, "cmd/compile/internal/coverage": true,
"cmd/compile/internal/deadlocals": true, "cmd/compile/internal/deadlocals": true,
@ -413,6 +420,7 @@ var bootstrap = map[string]bool{
"cmd/compile/internal/riscv64": true, "cmd/compile/internal/riscv64": true,
"cmd/compile/internal/rttype": true, "cmd/compile/internal/rttype": true,
"cmd/compile/internal/s390x": true, "cmd/compile/internal/s390x": true,
"cmd/compile/internal/slice": true,
"cmd/compile/internal/ssa": true, "cmd/compile/internal/ssa": true,
"cmd/compile/internal/ssagen": true, "cmd/compile/internal/ssagen": true,
"cmd/compile/internal/staticdata": true, "cmd/compile/internal/staticdata": true,

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,7 @@ const (
Var // "EOF" Var // "EOF"
Const // "Pi" Const // "Pi"
Field // "Point.X" Field // "Point.X"
Method // "(*Buffer).Grow" Method // "(*Buffer).Grow" or "(Reader).Read"
) )
func (kind Kind) String() string { func (kind Kind) String() string {

19
vendor/modules.txt vendored
View File

@ -285,18 +285,18 @@ github.com/xeipuuv/gojsonschema
# go.uber.org/atomic v1.11.0 # go.uber.org/atomic v1.11.0
## explicit; go 1.18 ## explicit; go 1.18
go.uber.org/atomic go.uber.org/atomic
# golang.org/x/crypto v0.46.0 # golang.org/x/crypto v0.48.0
## explicit; go 1.24.0 ## explicit; go 1.24.0
golang.org/x/crypto/acme golang.org/x/crypto/acme
golang.org/x/crypto/acme/autocert golang.org/x/crypto/acme/autocert
golang.org/x/crypto/bcrypt golang.org/x/crypto/bcrypt
golang.org/x/crypto/blowfish golang.org/x/crypto/blowfish
# golang.org/x/mod v0.30.0 # golang.org/x/mod v0.33.0
## explicit; go 1.24.0 ## explicit; go 1.24.0
golang.org/x/mod/internal/lazyregexp golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/module golang.org/x/mod/module
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.48.0 # golang.org/x/net v0.50.0
## explicit; go 1.24.0 ## explicit; go 1.24.0
golang.org/x/net/http/httpguts golang.org/x/net/http/httpguts
golang.org/x/net/http2 golang.org/x/net/http2
@ -304,15 +304,16 @@ golang.org/x/net/http2/h2c
golang.org/x/net/http2/hpack golang.org/x/net/http2/hpack
golang.org/x/net/idna golang.org/x/net/idna
golang.org/x/net/internal/httpcommon golang.org/x/net/internal/httpcommon
# golang.org/x/sync v0.19.0 golang.org/x/net/internal/httpsfv
## explicit; go 1.24.0 # golang.org/x/sync v0.20.0
## explicit; go 1.25.0
golang.org/x/sync/errgroup golang.org/x/sync/errgroup
# golang.org/x/sys v0.39.0 # golang.org/x/sys v0.41.0
## explicit; go 1.24.0 ## explicit; go 1.24.0
golang.org/x/sys/unix golang.org/x/sys/unix
golang.org/x/sys/windows golang.org/x/sys/windows
# golang.org/x/text v0.32.0 # golang.org/x/text v0.35.0
## explicit; go 1.24.0 ## explicit; go 1.25.0
golang.org/x/text/secure/bidirule golang.org/x/text/secure/bidirule
golang.org/x/text/transform golang.org/x/text/transform
golang.org/x/text/unicode/bidi golang.org/x/text/unicode/bidi
@ -320,7 +321,7 @@ golang.org/x/text/unicode/norm
# golang.org/x/time v0.14.0 # golang.org/x/time v0.14.0
## explicit; go 1.24.0 ## explicit; go 1.24.0
golang.org/x/time/rate golang.org/x/time/rate
# golang.org/x/tools v0.39.0 # golang.org/x/tools v0.42.0
## explicit; go 1.24.0 ## explicit; go 1.24.0
golang.org/x/tools/go/ast/astutil golang.org/x/tools/go/ast/astutil
golang.org/x/tools/go/buildutil golang.org/x/tools/go/buildutil