initial commit
This commit is contained in:
14
boolean/boolean.go
Normal file
14
boolean/boolean.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// boolean.go
|
||||||
|
package bocchi
|
||||||
|
|
||||||
|
import "git.sunturtle.xyz/zephyr/errors-my-beloved/boolean/secret"
|
||||||
|
|
||||||
|
var _ = map[bool]struct{}{
|
||||||
|
false: {},
|
||||||
|
secret.Secret == "gc25{}": {}, // ERROR: ./boolean.go:7:2: duplicate key false in map literal
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = map[bool]struct{}{
|
||||||
|
false: {},
|
||||||
|
secret.Secret[:5] != "gc25{": {}, // silently succeeds, even though it evaluates to false
|
||||||
|
}
|
3
boolean/go.mod
Normal file
3
boolean/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.sunturtle.xyz/zephyr/errors-my-beloved/boolean
|
||||||
|
|
||||||
|
go 1.25.0
|
3
boolean/secret/secret.go
Normal file
3
boolean/secret/secret.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package secret
|
||||||
|
|
||||||
|
const Secret = "gc25{afR7yRQVCRDy}"
|
7
distant/brain/brain.go
Normal file
7
distant/brain/brain.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package brain
|
||||||
|
|
||||||
|
type Interface interface {
|
||||||
|
Think(prefix []string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Think(s Interface, prompt string) (string, error) { panic("TODO") }
|
3
distant/brain/sqlbrain/brain.go
Normal file
3
distant/brain/sqlbrain/brain.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package sqlbrain
|
||||||
|
|
||||||
|
type Brain struct{} // SQL db
|
6
distant/brain/types.go
Normal file
6
distant/brain/types.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package brain
|
||||||
|
|
||||||
|
type (
|
||||||
|
Message struct{}
|
||||||
|
Tuple struct{}
|
||||||
|
)
|
3
distant/go.mod
Normal file
3
distant/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.sunturtle.xyz/zephyr/errors-my-beloved/distant
|
||||||
|
|
||||||
|
go 1.24.2
|
0
distant/go.sum
Normal file
0
distant/go.sum
Normal file
10
distant/main.go
Normal file
10
distant/main.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.sunturtle.xyz/zephyr/errors-my-beloved/distant/brain"
|
||||||
|
"git.sunturtle.xyz/zephyr/errors-my-beloved/distant/brain/sqlbrain"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
brain.Think(new(sqlbrain.Brain), "")
|
||||||
|
}
|
BIN
generated/bocchi.sqlite3
Normal file
BIN
generated/bocchi.sqlite3
Normal file
Binary file not shown.
11
generated/bocchi_test.go
Normal file
11
generated/bocchi_test.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package bocchi_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"git.sunturtle.xyz/zephyr/errors-my-beloved/generated/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// If a compiler error happens here, then the database schema has changed,
|
||||||
|
// so you need to update unit tests.
|
||||||
|
var _ [0]struct{} = [unsafe.Sizeof(models.Bocchi{}) - 56]struct{}{}
|
3
generated/go.mod
Normal file
3
generated/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.sunturtle.xyz/zephyr/errors-my-beloved/generated
|
||||||
|
|
||||||
|
go 1.25.0
|
147
generated/models/bocchi.xo.go
Normal file
147
generated/models/bocchi.xo.go
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
// Package models contains generated code for schema 'bocchi.sqlite3'.
|
||||||
|
package models
|
||||||
|
|
||||||
|
// Code generated by xo. DO NOT EDIT.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bocchi represents a row from 'bocchi'.
|
||||||
|
type Bocchi struct {
|
||||||
|
ID sql.NullString `json:"id"` // id
|
||||||
|
Name sql.NullString `json:"name"` // name
|
||||||
|
Performances sql.NullInt64 `json:"performances"` // performances
|
||||||
|
// xo fields
|
||||||
|
_exists, _deleted bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exists returns true when the [Bocchi] exists in the database.
|
||||||
|
func (b *Bocchi) Exists() bool {
|
||||||
|
return b._exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleted returns true when the [Bocchi] has been marked for deletion
|
||||||
|
// from the database.
|
||||||
|
func (b *Bocchi) Deleted() bool {
|
||||||
|
return b._deleted
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert inserts the [Bocchi] to the database.
|
||||||
|
func (b *Bocchi) Insert(ctx context.Context, db DB) error {
|
||||||
|
switch {
|
||||||
|
case b._exists: // already exists
|
||||||
|
return logerror(&ErrInsertFailed{ErrAlreadyExists})
|
||||||
|
case b._deleted: // deleted
|
||||||
|
return logerror(&ErrInsertFailed{ErrMarkedForDeletion})
|
||||||
|
}
|
||||||
|
// insert (manual)
|
||||||
|
const sqlstr = `INSERT INTO bocchi (` +
|
||||||
|
`id, name, performances` +
|
||||||
|
`) VALUES (` +
|
||||||
|
`$1, $2, $3` +
|
||||||
|
`)`
|
||||||
|
// run
|
||||||
|
logf(sqlstr, b.ID, b.Name, b.Performances)
|
||||||
|
if _, err := db.ExecContext(ctx, sqlstr, b.ID, b.Name, b.Performances); err != nil {
|
||||||
|
return logerror(err)
|
||||||
|
}
|
||||||
|
// set exists
|
||||||
|
b._exists = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates a [Bocchi] in the database.
|
||||||
|
func (b *Bocchi) Update(ctx context.Context, db DB) error {
|
||||||
|
switch {
|
||||||
|
case !b._exists: // doesn't exist
|
||||||
|
return logerror(&ErrUpdateFailed{ErrDoesNotExist})
|
||||||
|
case b._deleted: // deleted
|
||||||
|
return logerror(&ErrUpdateFailed{ErrMarkedForDeletion})
|
||||||
|
}
|
||||||
|
// update with primary key
|
||||||
|
const sqlstr = `UPDATE bocchi SET ` +
|
||||||
|
`name = $1, performances = $2 ` +
|
||||||
|
`WHERE id = $3`
|
||||||
|
// run
|
||||||
|
logf(sqlstr, b.Name, b.Performances, b.ID)
|
||||||
|
if _, err := db.ExecContext(ctx, sqlstr, b.Name, b.Performances, b.ID); err != nil {
|
||||||
|
return logerror(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save saves the [Bocchi] to the database.
|
||||||
|
func (b *Bocchi) Save(ctx context.Context, db DB) error {
|
||||||
|
if b.Exists() {
|
||||||
|
return b.Update(ctx, db)
|
||||||
|
}
|
||||||
|
return b.Insert(ctx, db)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upsert performs an upsert for [Bocchi].
|
||||||
|
func (b *Bocchi) Upsert(ctx context.Context, db DB) error {
|
||||||
|
switch {
|
||||||
|
case b._deleted: // deleted
|
||||||
|
return logerror(&ErrUpsertFailed{ErrMarkedForDeletion})
|
||||||
|
}
|
||||||
|
// upsert
|
||||||
|
const sqlstr = `INSERT INTO bocchi (` +
|
||||||
|
`id, name, performances` +
|
||||||
|
`) VALUES (` +
|
||||||
|
`$1, $2, $3` +
|
||||||
|
`)` +
|
||||||
|
` ON CONFLICT (id) DO ` +
|
||||||
|
`UPDATE SET ` +
|
||||||
|
`name = EXCLUDED.name, performances = EXCLUDED.performances `
|
||||||
|
// run
|
||||||
|
logf(sqlstr, b.ID, b.Name, b.Performances)
|
||||||
|
if _, err := db.ExecContext(ctx, sqlstr, b.ID, b.Name, b.Performances); err != nil {
|
||||||
|
return logerror(err)
|
||||||
|
}
|
||||||
|
// set exists
|
||||||
|
b._exists = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes the [Bocchi] from the database.
|
||||||
|
func (b *Bocchi) Delete(ctx context.Context, db DB) error {
|
||||||
|
switch {
|
||||||
|
case !b._exists: // doesn't exist
|
||||||
|
return nil
|
||||||
|
case b._deleted: // deleted
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// delete with single primary key
|
||||||
|
const sqlstr = `DELETE FROM bocchi ` +
|
||||||
|
`WHERE id = $1`
|
||||||
|
// run
|
||||||
|
logf(sqlstr, b.ID)
|
||||||
|
if _, err := db.ExecContext(ctx, sqlstr, b.ID); err != nil {
|
||||||
|
return logerror(err)
|
||||||
|
}
|
||||||
|
// set deleted
|
||||||
|
b._deleted = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BocchiByID retrieves a row from 'bocchi' as a [Bocchi].
|
||||||
|
//
|
||||||
|
// Generated from index 'sqlite_autoindex_bocchi_1'.
|
||||||
|
func BocchiByID(ctx context.Context, db DB, id sql.NullString) (*Bocchi, error) {
|
||||||
|
// query
|
||||||
|
const sqlstr = `SELECT ` +
|
||||||
|
`id, name, performances ` +
|
||||||
|
`FROM bocchi ` +
|
||||||
|
`WHERE id = $1`
|
||||||
|
// run
|
||||||
|
logf(sqlstr, id)
|
||||||
|
b := Bocchi{
|
||||||
|
_exists: true,
|
||||||
|
}
|
||||||
|
if err := db.QueryRowContext(ctx, sqlstr, id).Scan(&b.ID, &b.Name, &b.Performances); err != nil {
|
||||||
|
return nil, logerror(err)
|
||||||
|
}
|
||||||
|
return &b, nil
|
||||||
|
}
|
240
generated/models/db.xo.go
Normal file
240
generated/models/db.xo.go
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// Code generated by xo. DO NOT EDIT.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// logf is used by generated code to log SQL queries.
|
||||||
|
logf = func(string, ...interface{}) {}
|
||||||
|
// errf is used by generated code to log SQL errors.
|
||||||
|
errf = func(string, ...interface{}) {}
|
||||||
|
)
|
||||||
|
|
||||||
|
// logerror logs the error and returns it.
|
||||||
|
func logerror(err error) error {
|
||||||
|
errf("ERROR: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logf logs a message using the package logger.
|
||||||
|
func Logf(s string, v ...interface{}) {
|
||||||
|
logf(s, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLogger sets the package logger. Valid logger types:
|
||||||
|
//
|
||||||
|
// io.Writer
|
||||||
|
// func(string, ...interface{}) (int, error) // fmt.Printf
|
||||||
|
// func(string, ...interface{}) // log.Printf
|
||||||
|
func SetLogger(logger interface{}) {
|
||||||
|
logf = convLogger(logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf logs an error message using the package error logger.
|
||||||
|
func Errorf(s string, v ...interface{}) {
|
||||||
|
errf(s, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetErrorLogger sets the package error logger. Valid logger types:
|
||||||
|
//
|
||||||
|
// io.Writer
|
||||||
|
// func(string, ...interface{}) (int, error) // fmt.Printf
|
||||||
|
// func(string, ...interface{}) // log.Printf
|
||||||
|
func SetErrorLogger(logger interface{}) {
|
||||||
|
errf = convLogger(logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convLogger converts logger to the standard logger interface.
|
||||||
|
func convLogger(logger interface{}) func(string, ...interface{}) {
|
||||||
|
switch z := logger.(type) {
|
||||||
|
case io.Writer:
|
||||||
|
return func(s string, v ...interface{}) {
|
||||||
|
fmt.Fprintf(z, s, v...)
|
||||||
|
}
|
||||||
|
case func(string, ...interface{}) (int, error): // fmt.Printf
|
||||||
|
return func(s string, v ...interface{}) {
|
||||||
|
_, _ = z(s, v...)
|
||||||
|
}
|
||||||
|
case func(string, ...interface{}): // log.Printf
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("unsupported logger type %T", logger))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DB is the common interface for database operations that can be used with
|
||||||
|
// types from schema 'bocchi.sqlite3'.
|
||||||
|
//
|
||||||
|
// This works with both [database/sql.DB] and [database/sql.Tx].
|
||||||
|
type DB interface {
|
||||||
|
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
||||||
|
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
||||||
|
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error is an error.
|
||||||
|
type Error string
|
||||||
|
|
||||||
|
// Error satisfies the error interface.
|
||||||
|
func (err Error) Error() string {
|
||||||
|
return string(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error values.
|
||||||
|
const (
|
||||||
|
// ErrAlreadyExists is the already exists error.
|
||||||
|
ErrAlreadyExists Error = "already exists"
|
||||||
|
// ErrDoesNotExist is the does not exist error.
|
||||||
|
ErrDoesNotExist Error = "does not exist"
|
||||||
|
// ErrMarkedForDeletion is the marked for deletion error.
|
||||||
|
ErrMarkedForDeletion Error = "marked for deletion"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrInsertFailed is the insert failed error.
|
||||||
|
type ErrInsertFailed struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error satisfies the error interface.
|
||||||
|
func (err *ErrInsertFailed) Error() string {
|
||||||
|
return fmt.Sprintf("insert failed: %v", err.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap satisfies the unwrap interface.
|
||||||
|
func (err *ErrInsertFailed) Unwrap() error {
|
||||||
|
return err.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrUpdateFailed is the update failed error.
|
||||||
|
type ErrUpdateFailed struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error satisfies the error interface.
|
||||||
|
func (err *ErrUpdateFailed) Error() string {
|
||||||
|
return fmt.Sprintf("update failed: %v", err.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap satisfies the unwrap interface.
|
||||||
|
func (err *ErrUpdateFailed) Unwrap() error {
|
||||||
|
return err.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrUpsertFailed is the upsert failed error.
|
||||||
|
type ErrUpsertFailed struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error satisfies the error interface.
|
||||||
|
func (err *ErrUpsertFailed) Error() string {
|
||||||
|
return fmt.Sprintf("upsert failed: %v", err.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap satisfies the unwrap interface.
|
||||||
|
func (err *ErrUpsertFailed) Unwrap() error {
|
||||||
|
return err.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrInvalidTime is the invalid Time error.
|
||||||
|
type ErrInvalidTime string
|
||||||
|
|
||||||
|
// Error satisfies the error interface.
|
||||||
|
func (err ErrInvalidTime) Error() string {
|
||||||
|
return fmt.Sprintf("invalid Time (%s)", string(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time is a SQLite3 Time that scans for the various timestamps values used by
|
||||||
|
// SQLite3 database drivers to store time.Time values.
|
||||||
|
type Time struct {
|
||||||
|
time time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTime creates a time.
|
||||||
|
func NewTime(t time.Time) Time {
|
||||||
|
return Time{time: t}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String satisfies the fmt.Stringer interface.
|
||||||
|
func (t Time) String() string {
|
||||||
|
return t.time.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format formats the time.
|
||||||
|
func (t Time) Format(layout string) string {
|
||||||
|
return t.time.Format(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time returns a time.Time.
|
||||||
|
func (t Time) Time() time.Time {
|
||||||
|
return t.time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value satisfies the sql/driver.Valuer interface.
|
||||||
|
func (t Time) Value() (driver.Value, error) {
|
||||||
|
return t.time, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan satisfies the sql.Scanner interface.
|
||||||
|
func (t *Time) Scan(v interface{}) error {
|
||||||
|
switch x := v.(type) {
|
||||||
|
case time.Time:
|
||||||
|
t.time = x
|
||||||
|
return nil
|
||||||
|
case []byte:
|
||||||
|
return t.Parse(string(x))
|
||||||
|
case string:
|
||||||
|
return t.Parse(x)
|
||||||
|
}
|
||||||
|
return ErrInvalidTime(fmt.Sprintf("%T", v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse attempts to Parse string s to t.
|
||||||
|
func (t *Time) Parse(s string) error {
|
||||||
|
if s == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, f := range TimestampFormats {
|
||||||
|
if z, err := time.Parse(f, s); err == nil {
|
||||||
|
t.time = z
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ErrInvalidTime(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON satisfies the [json.Marshaler] interface.
|
||||||
|
func (t Time) MarshalJSON() ([]byte, error) {
|
||||||
|
return t.time.MarshalJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON satisfies the [json.Unmarshaler] interface.
|
||||||
|
func (t *Time) UnmarshalJSON(data []byte) error {
|
||||||
|
return t.time.UnmarshalJSON(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampFormats are the timestamp formats used by SQLite3 database drivers
|
||||||
|
// to store a time.Time in SQLite3.
|
||||||
|
//
|
||||||
|
// The first format in the slice will be used when saving time values into the
|
||||||
|
// database. When parsing a string from a timestamp or datetime column, the
|
||||||
|
// formats are tried in order.
|
||||||
|
var TimestampFormats = []string{
|
||||||
|
// By default, use timestamps with the timezone they have. When parsed,
|
||||||
|
// they will be returned with the same timezone.
|
||||||
|
"2006-01-02 15:04:05.999999999-07:00",
|
||||||
|
"2006-01-02T15:04:05.999999999-07:00",
|
||||||
|
"2006-01-02 15:04:05.999999999",
|
||||||
|
"2006-01-02T15:04:05.999999999",
|
||||||
|
"2006-01-02 15:04:05",
|
||||||
|
"2006-01-02T15:04:05",
|
||||||
|
"2006-01-02 15:04",
|
||||||
|
"2006-01-02T15:04",
|
||||||
|
"2006-01-02",
|
||||||
|
}
|
5
generated/schema.sql
Normal file
5
generated/schema.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE bocchi (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
performances INTEGER
|
||||||
|
);
|
10
go.work
Normal file
10
go.work
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
go 1.25.0
|
||||||
|
|
||||||
|
use (
|
||||||
|
./boolean
|
||||||
|
./distant
|
||||||
|
./generated
|
||||||
|
./iface
|
||||||
|
./sizeofstring
|
||||||
|
./stringer
|
||||||
|
)
|
11
iface/01-iface.go
Normal file
11
iface/01-iface.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type Strummer interface {
|
||||||
|
Strum()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bocchi struct {
|
||||||
|
Guitar string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Strummer = (*Bocchi)(nil)
|
3
iface/go.mod
Normal file
3
iface/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.sunturtle.xyz/zephyr/errors-my-beloved/iface
|
||||||
|
|
||||||
|
go 1.24.2
|
3
sizeofstring/go.mod
Normal file
3
sizeofstring/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.sunturtle.xyz/zephyr/errors-my-beloved/sizeofstring
|
||||||
|
|
||||||
|
go 1.25.0
|
13
sizeofstring/step1.go
Normal file
13
sizeofstring/step1.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
// step1.go
|
||||||
|
package bocchi
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type Bocchi struct {
|
||||||
|
x uint32
|
||||||
|
y uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ [0]struct{} = [unsafe.Sizeof(Bocchi{}) - 0]struct{}{}
|
13
sizeofstring/step2.go
Normal file
13
sizeofstring/step2.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
// step2.go
|
||||||
|
package bocchi
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type Bocchi struct {
|
||||||
|
x uint32
|
||||||
|
y uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ [0]struct{} = [unsafe.Sizeof(Bocchi{}) - 16]struct{}{}
|
18
sizeofstring/step3.go
Normal file
18
sizeofstring/step3.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package bocchi
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type Bocchi struct {
|
||||||
|
x uint32
|
||||||
|
y uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// step3.go
|
||||||
|
var (
|
||||||
|
// assert Bocchi.x doesn't move
|
||||||
|
_ [0]struct{} = [unsafe.Offsetof(Bocchi{}.x) - 0]struct{}{}
|
||||||
|
// assert Bocchi.y comes next after Bocchi.x
|
||||||
|
_ [0]struct{} = [unsafe.Offsetof(Bocchi{}.y) - (unsafe.Alignof(Bocchi{}.y))]struct{}{}
|
||||||
|
// assert y is the last field in Bocchi
|
||||||
|
_ [0]struct{} = [unsafe.Sizeof(Bocchi{}) - (unsafe.Alignof(Bocchi{}.y) + unsafe.Sizeof(Bocchi{}.y))]struct{}{}
|
||||||
|
)
|
3
stringer/go.mod
Normal file
3
stringer/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module git.sunturtle.xyz/zephyr/errors-my-beloved/stringer
|
||||||
|
|
||||||
|
go 1.24.2
|
14
stringer/kessoku/band.go
Normal file
14
stringer/kessoku/band.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package kessoku
|
||||||
|
|
||||||
|
type BandMember int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Bocchi BandMember = iota
|
||||||
|
Ryo
|
||||||
|
Nijika
|
||||||
|
Kita
|
||||||
|
|
||||||
|
maxBand
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ [0]struct{} = [maxBand - 4]struct{}{}
|
27
stringer/kessoku/bandmember_string.go
Normal file
27
stringer/kessoku/bandmember_string.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Code generated by "stringer -type BandMember ./03-stringer/kessoku/"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package kessoku
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[Bocchi-0]
|
||||||
|
_ = x[Ryo-1]
|
||||||
|
_ = x[Nijika-2]
|
||||||
|
_ = x[Kita-3]
|
||||||
|
_ = x[maxBand-4]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _BandMember_name = "BocchiRyoNijikaKitamaxBand"
|
||||||
|
|
||||||
|
var _BandMember_index = [...]uint8{0, 6, 9, 15, 19, 26}
|
||||||
|
|
||||||
|
func (i BandMember) String() string {
|
||||||
|
if i < 0 || i >= BandMember(len(_BandMember_index)-1) {
|
||||||
|
return "BandMember(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _BandMember_name[_BandMember_index[i]:_BandMember_index[i+1]]
|
||||||
|
}
|
Reference in New Issue
Block a user