From daae2f00d4a20afa8a89f111bcfa5ecd9d994412 Mon Sep 17 00:00:00 2001 From: blead Date: Wed, 10 Jan 2024 23:50:27 +0700 Subject: [PATCH] Implement comics fetching, add support for TW server --- README.md | 6 + cmd/fetch.go | 8 +- pkg/wf/client.go | 449 +++++++++++++++++++----- pkg/wf/client_gen.go | 719 ++++++++++++++++++++++++++++++++++++++ pkg/wf/client_gen_test.go | 462 ++++++++++++++++++++++++ 5 files changed, 1559 insertions(+), 85 deletions(-) create mode 100644 pkg/wf/client_gen.go create mode 100644 pkg/wf/client_gen_test.go diff --git a/README.md b/README.md index 5bf7c0d..d45e815 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,11 @@ Fetch new (`diff-only`) assets for version `1.600.0` into `./dump` directory and wfax fetch --diff-only --version 1.600.0 ./dump && wfax extract --indent 2 ./dump ./output ``` +Fetch character comics (`--comics 1`) with `10` maximum concurrent requests into `./comics` directory. +```sh +wfax fetch --comics 1 --concurrency 10 ./comics +``` + Extract character image assets for eliyabot: ```sh wfax extract --eliyabot --no-default-paths ./dump ./output @@ -44,3 +49,4 @@ The main focus currently is extracting text files so other assets are not fully * Ordered Maps * Action/Enemy DSL files * Image assets for EliyaBot +* Comics diff --git a/cmd/fetch.go b/cmd/fetch.go index 6d1aa9c..b894370 100644 --- a/cmd/fetch.go +++ b/cmd/fetch.go @@ -13,6 +13,7 @@ var fetchVersion string var fetchDiff bool var fetchConcurrency int var fetchRegion string +var fetchComics int var fetchCmd = &cobra.Command{ Use: "fetch [target dir]", @@ -39,6 +40,8 @@ var fetchCmd = &cobra.Command{ config.Region = wf.RegionKR case "cn": config.Region = wf.RegionCN + case "tw": + config.Region = wf.RegionTW default: log.Printf("[WARN] Unknown service region %s, using default (jp)", fetchRegion) config.Region = wf.RegionJP @@ -49,7 +52,7 @@ var fetchCmd = &cobra.Command{ log.Fatalln(err) } - err = client.FetchAssetsFromAPI() + err = client.FetchAssetsFromAPI(fetchComics) if err != nil { if err == wf.ErrNoNewAssets { os.Exit(1) @@ -64,5 +67,6 @@ func init() { fetchCmd.Flags().StringVarP(&fetchVersion, "version", "v", "0.0.0", "Game version of existing assets") fetchCmd.Flags().BoolVarP(&fetchDiff, "diff-only", "d", false, "Fetch only new assets (used with --version)") fetchCmd.Flags().IntVarP(&fetchConcurrency, "concurrency", "c", 5, "Maximum number of concurrent asset downloads") - fetchCmd.Flags().StringVarP(&fetchRegion, "region", "r", "jp", "Service region: jp, gl, kr, cn") + fetchCmd.Flags().StringVarP(&fetchRegion, "region", "r", "jp", "Service region: jp, gl, kr, cn, tw") + fetchCmd.Flags().IntVarP(&fetchComics, "comics", "m", 0, "Fetch comics instead (1: character comics, 2: tutorial comics)") } diff --git a/pkg/wf/client.go b/pkg/wf/client.go index 48c7ab9..107eb9c 100644 --- a/pkg/wf/client.go +++ b/pkg/wf/client.go @@ -3,15 +3,18 @@ package wf import ( "bytes" "encoding/base64" + "encoding/json" "errors" "fmt" "io" "log" + "math" "net/http" "os" "path" "path/filepath" "regexp" + "sort" "strings" "github.com/Jeffail/gabs/v2" @@ -21,14 +24,22 @@ import ( ) const ( - defaultVersion = "0.0.0" - dumpAssetDir = "upload" - apiEndpointJP = "https://api.worldflipper.jp/latest/api/index.php/gacha/exec" - apiEndpointGL = "https://na.wdfp.kakaogames.com/latest/api/index.php/gacha/exec" - apiEndpointKR = "https://kr.wdfp.kakaogames.com/latest/api/index.php/gacha/exec" - apiEndpointCN = "https://shijtswygamegf.leiting.com/latest/api/index.php/gacha/exec" - cdnAddressGL = "http://patch.wdfp.kakaogames.com/Live/2.0.0" - cdnAddressKR = "http://patch.wdfp.kakaogames.com/Live/2.0.0" + defaultVersion = "0.0.0" + dumpAssetDir = "upload" + apiHostJP = "https://api.worldflipper.jp" + apiHostGL = "https://na.wdfp.kakaogames.com" + apiHostKR = "https://kr.wdfp.kakaogames.com" + apiHostCN = "https://shijtswygamegf.leiting.com" + apiHostTW = "https://wf-game.worldflipper.beanfun.com" + apiAssetEndpoint = "/latest/api/index.php/gacha/exec" + apiComicEndpoint = "/latest/api/index.php/comic/get_list" + cdnAddressGL = "http://patch.wdfp.kakaogames.com/Live/2.0.0" + cdnAddressKR = "http://patch.wdfp.kakaogames.com/Live/2.0.0" + viewerIDJP = 938889939 + viewerIDGL = 752309378 + viewerIDKR = 885870369 + viewerIDCN = 554279419 + viewerIDTW = 714420616 ) var ErrNoNewAssets = errors.New("no new assets") @@ -50,21 +61,27 @@ const ( RegionGL RegionKR RegionCN + RegionTW ) -func getAPIEndpoint(region ServiceRegion) string { +func getAPIEndpoint(region ServiceRegion, endpoint string) string { + if endpoint == "" { + endpoint = apiAssetEndpoint + } switch region { case RegionJP: - return apiEndpointJP + return apiHostJP + endpoint case RegionGL: - return apiEndpointGL + return apiHostGL + endpoint case RegionKR: - return apiEndpointKR + return apiHostKR + endpoint case RegionCN: - return apiEndpointCN + return apiHostCN + endpoint + case RegionTW: + return apiHostTW + endpoint } - log.Printf("[WARN] getAPIEndpoint: unknown region, using default (JP), region=%v\n", region) - return apiEndpointJP + log.Printf("[WARN] getAPIEndpoint: unknown region, using default (JP), region=%v, endpoint=%v\n", region, endpoint) + return apiHostJP + endpoint } func getCDNAddress(region ServiceRegion) string { @@ -85,6 +102,23 @@ func replaceCDNAddress(location string, region ServiceRegion) string { return location } +func getViewerID(region ServiceRegion) int { + switch region { + case RegionJP: + return viewerIDJP + case RegionGL: + return viewerIDGL + case RegionKR: + return viewerIDKR + case RegionCN: + return viewerIDCN + case RegionTW: + return viewerIDTW + } + log.Printf("[WARN] getViewerID: unknown region, using default (JP), region=%v\n", region) + return viewerIDJP +} + // ClientConfig is the configuration for the client. type ClientConfig struct { Version string @@ -168,13 +202,7 @@ func clientHeader(version string, region ServiceRegion) *http.Header { return header } -func (client *Client) fetchMetadata() ([]byte, error) { - req, err := retryablehttp.NewRequest("GET", getAPIEndpoint(client.config.Region), nil) - if err != nil { - return nil, err - } - - req.Header = *client.header +func (client *Client) fetchMsgp(req *retryablehttp.Request) ([]byte, error) { resp, err := client.client.Do(req) if err != nil { return nil, err @@ -192,11 +220,11 @@ func (client *Client) fetchMetadata() ([]byte, error) { type assetMetadata struct { location string - size int + dest string sha256 string } -func (client *Client) parseMetadata(json []byte) (string, []*assetMetadata, error) { +func (client *Client) parseMetadata(json []byte, parseAssets bool) (string, []*assetMetadata, error) { jsonParsed, err := gabs.ParseJSON(json) if err != nil { return "", nil, err @@ -211,22 +239,25 @@ func (client *Client) parseMetadata(json []byte) (string, []*assetMetadata, erro } var assets []*assetMetadata - if client.config.Mode == FullAssets { - for _, child := range jsonParsed.Path("data.full.archive").Children() { - assets = append(assets, &assetMetadata{ - location: replaceCDNAddress(child.Path("location").Data().(string), client.config.Region), - size: int(child.Path("size").Data().(float64)), - sha256: child.Path("sha256").Data().(string), - }) + + if parseAssets { + if client.config.Mode == FullAssets { + for _, child := range jsonParsed.Path("data.full.archive").Children() { + assets = append(assets, &assetMetadata{ + location: replaceCDNAddress(child.Path("location").Data().(string), client.config.Region), + dest: client.tmpDir, + sha256: child.Path("sha256").Data().(string), + }) + } } - } - for _, group := range jsonParsed.Search("data", "diff", "*", "archive").Children() { - for _, child := range group.Children() { - assets = append(assets, &assetMetadata{ - location: replaceCDNAddress(child.Path("location").Data().(string), client.config.Region), - size: int(child.Path("size").Data().(float64)), - sha256: child.Path("sha256").Data().(string), - }) + for _, group := range jsonParsed.Search("data", "diff", "*", "archive").Children() { + for _, child := range group.Children() { + assets = append(assets, &assetMetadata{ + location: replaceCDNAddress(child.Path("location").Data().(string), client.config.Region), + dest: client.tmpDir, + sha256: child.Path("sha256").Data().(string), + }) + } } } @@ -251,20 +282,28 @@ func (client *Client) download(i *concurrency.Item[*assetMetadata, []string]) ([ return nil, err } - // Compare checksum - expected, err := base64.StdEncoding.DecodeString(a.sha256) - if err != nil { - return nil, err + if a.sha256 != "" { + // Compare checksum + expected, err := base64.StdEncoding.DecodeString(a.sha256) + if err != nil { + return nil, err + } + downloaded, err := sha256Checksum(bytes.NewReader(body)) + if err != nil { + return nil, err + } + if !bytes.Equal(expected, downloaded) { + return nil, fmt.Errorf("download: sha256 mismatch, expected: %x, downloaded: %x", expected, downloaded) + } } - downloaded, err := sha256Checksum(bytes.NewReader(body)) + + dest := filepath.Join(a.dest, path.Base(a.location)) + + err = os.MkdirAll(filepath.Dir(dest), 0777) if err != nil { - return nil, err - } - if !bytes.Equal(expected, downloaded) { - return nil, fmt.Errorf("download: sha256 mismatch, expected: %x, downloaded: %x", expected, downloaded) + return nil, fmt.Errorf("download: dest mkdir error, path=%s, %w", dest, err) } - dest := filepath.Join(client.tmpDir, path.Base(a.location)) destFile, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return nil, fmt.Errorf("download: open error, path=%s, %w", dest, err) @@ -281,12 +320,15 @@ func (client *Client) download(i *concurrency.Item[*assetMetadata, []string]) ([ return nil, fmt.Errorf("download: write error, path=%s, %w", dest, err) } - // return list of files - return lszip( - bytes.NewReader(body), - int64(len(body)), - modPath, - ) + if a.sha256 != "" { + // return list of files + return lszip( + bytes.NewReader(body), + int64(len(body)), + modPath, + ) + } + return nil, nil } type extractMapPair struct { @@ -343,7 +385,7 @@ func (client *Client) extract(i *concurrency.Item[*assetMetadata, []string]) ([] return nil, err } -func (client *Client) downloadAndExtract(assets []*assetMetadata) error { +func (client *Client) downloadAssets(assets []*assetMetadata) ([]*concurrency.Item[*assetMetadata, []string], error) { var items []*concurrency.Item[*assetMetadata, []string] for _, a := range assets { items = append(items, &concurrency.Item[*assetMetadata, []string]{ @@ -353,28 +395,21 @@ func (client *Client) downloadAndExtract(assets []*assetMetadata) error { }) } - err := os.MkdirAll(client.config.Workdir, 0777) - if err != nil { - return err - } - tmpDir, err := os.MkdirTemp(client.config.Workdir, "fetchtmp") - if err != nil { - return err - } - defer func() { - err := os.RemoveAll(tmpDir) - if err != nil { - log.Fatal(fmt.Errorf("downloadAndExtract: remove error, path=%s, %w", tmpDir, err)) - } - }() - - client.tmpDir = tmpDir con := client.config.Concurrency if len(items) < con { con = len(items) } - err = concurrency.Execute(client.download, items, con) + err := concurrency.Execute(client.download, items, con) + if err != nil { + return nil, err + } + + return items, nil +} + +func (client *Client) downloadAndExtract(assets []*assetMetadata) error { + items, err := client.downloadAssets(assets) if err != nil { return err } @@ -412,32 +447,280 @@ func (client *Client) downloadAndExtract(assets []*assetMetadata) error { } client.extractMap = extMaps[0].Output + con := client.config.Concurrency + if len(items) < con { + con = len(items) + } + return concurrency.Execute(client.extract, items, con) } +//go:generate msgp +type ComicListRequestBody struct { + PageIndex int `msg:"page_index"` + Kind int `msg:"kind"` // 0 = char comics, 1 = guide comics + ViewerID int `msg:"viewer_id"` +} + +func (client *Client) buildComicListRequest(comicListReq *ComicListRequestBody) (*retryablehttp.Request, error) { + var body bytes.Buffer + encoder := base64.NewEncoder(base64.StdEncoding, &body) + err := msgp.Encode(encoder, comicListReq) + if err != nil { + return nil, err + } + err = encoder.Close() + if err != nil { + return nil, err + } + + req, err := retryablehttp.NewRequest("POST", getAPIEndpoint(client.config.Region, apiComicEndpoint), &body) + if err != nil { + return nil, err + } + + req.Header = client.header.Clone() + req.Header.Set("APP_VER", "999.999.999") + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("DEVICE", "2") + req.Header.Set("GAME-APP-ID", fmt.Sprintf("%d", getViewerID(client.config.Region))) + req.Header.Set("Referer", "app:/worldflipper_android_release.swf") + req.Header.Set("UDID", "BC51B46F-B7D5-49C3-A651-62D255A49C8471D9") + req.Header.Set("x-flash-version", "50,2,2,6") + + param, err := sha1Digest(req.Header.Get("UDID")+req.Header.Get("GAME-APP-ID")+apiComicEndpoint+body.String(), "") + if err != nil { + return nil, err + } + req.Header.Set("PARAM", param) + + return req, nil +} + +type ComicMetadata struct { + Episode int `json:"episode"` + Title string `json:"title"` + CommenceTime string `json:"commenceTime"` +} + +func (client *Client) parseComicList(data []byte) (int, []*assetMetadata, []*ComicMetadata, error) { + dec := json.NewDecoder(bytes.NewReader(data)) + dec.UseNumber() + jsonParsed, err := gabs.ParseJSONDecoder(dec) + if err != nil || !jsonParsed.ExistsP("data.comic_list") { + return 0, nil, nil, err + } + + count, err := jsonParsed.Path("data.total_count").Data().(json.Number).Int64() + if err != nil { + return 0, nil, nil, fmt.Errorf("parseComicList: unable to parse total count, %w", err) + } + + var assets []*assetMetadata + var comics []*ComicMetadata + for _, child := range jsonParsed.Path("data.comic_list").Children() { + episode, _ := child.Path("episode").Data().(json.Number).Int64() + dest := filepath.Join(client.config.Workdir, fmt.Sprintf("%d", episode)) + assets = append(assets, &assetMetadata{ + location: child.Path("media_image.main").Data().(string), + dest: dest, + sha256: "", + }) + assets = append(assets, &assetMetadata{ + location: child.Path("media_image.thumbnail_s").Data().(string), + dest: dest, + sha256: "", + }) + assets = append(assets, &assetMetadata{ + location: child.Path("media_image.thumbnail_l").Data().(string), + dest: dest, + sha256: "", + }) + comics = append(comics, &ComicMetadata{ + Episode: int(episode), + Title: child.Path("title").Data().(string), + CommenceTime: child.Path("commence_time").Data().(string), + }) + } + + return int(count), assets, comics, nil +} + +type comicListOutput struct { + assets []*assetMetadata + comics []*ComicMetadata +} + +func (client *Client) downloadComicList(i *concurrency.Item[*ComicListRequestBody, *comicListOutput]) (*comicListOutput, error) { + comicListReq, err := client.buildComicListRequest(i.Data) + if err != nil { + return nil, err + } + + comicList, err := client.fetchMsgp(comicListReq) + if err != nil { + return nil, err + } + + _, assets, comics, err := client.parseComicList(comicList) + if err != nil { + return nil, err + } + + return &comicListOutput{assets: assets, comics: comics}, nil +} + +func (client *Client) fetchComicsMetadata(kind int, version string) ([]*assetMetadata, error) { + client.header.Set("RES_VER", version) + + comicListReq, err := client.buildComicListRequest(&ComicListRequestBody{ + ViewerID: getViewerID(client.config.Region), + Kind: kind, + PageIndex: 0, + }) + if err != nil { + return nil, err + } + + comicList, err := client.fetchMsgp(comicListReq) + if err != nil { + return nil, err + } + + count, assets, comics, err := client.parseComicList(comicList) + if err != nil { + return nil, err + } + + var items []*concurrency.Item[*ComicListRequestBody, *comicListOutput] + pages := int(math.Ceil(float64(count) / float64(len(comics)))) + for i := 1; i <= pages; i++ { + items = append(items, &concurrency.Item[*ComicListRequestBody, *comicListOutput]{ + Data: &ComicListRequestBody{ + ViewerID: getViewerID(client.config.Region), + Kind: kind, + PageIndex: i, + }, + Output: nil, + Err: nil, + }) + } + + con := client.config.Concurrency + if len(items) < con { + con = len(items) + } + + err = concurrency.Execute(client.downloadComicList, items, con) + if err != nil { + return nil, err + } + + for _, i := range items { + if i.Output != nil { + if i.Output.comics != nil { + comics = append(comics, i.Output.comics...) + } + if i.Output.assets != nil { + assets = append(assets, i.Output.assets...) + } + } + } + sort.Slice(comics, func(i, j int) bool { + return comics[i].Episode < comics[j].Episode + }) + + f, err := os.OpenFile(filepath.Join(client.config.Workdir, "metadata.json"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return nil, err + } + defer func() { + err := f.Close() + if err != nil { + log.Fatalln(err) + } + }() + + enc := json.NewEncoder(f) + enc.SetEscapeHTML(false) + err = enc.Encode(comics) + if err != nil { + return nil, err + } + + return assets, nil +} + // FetchAssetsFromAPI fetches metadata from API then download and extract the assets archives. -func (client *Client) FetchAssetsFromAPI() error { +func (client *Client) FetchAssetsFromAPI(fetchComics int) error { + if fetchComics < 0 || fetchComics > 2 { + log.Println("[WARN] Invalid comics id supplied, fetching character comics (1) instead") + fetchComics = 1 + } + if client.config.Region == RegionCN { + log.Println("[WARN] CN region is untested due to region block") + } + log.Println("[INFO] Fetching asset metadata, clientVersion=" + client.config.Version) - metadata, err := client.fetchMetadata() + metadataReq, err := retryablehttp.NewRequest("GET", getAPIEndpoint(client.config.Region, apiAssetEndpoint), nil) if err != nil { return err } - latestVersion, assets, err := client.parseMetadata(metadata) + metadataReq.Header = *client.header + metadata, err := client.fetchMsgp(metadataReq) if err != nil { return err } - if len(assets) == 0 { - log.Println("[INFO] No new assets") - return ErrNoNewAssets + + err = os.MkdirAll(client.config.Workdir, 0777) + if err != nil { + return err + } + + if fetchComics != 1 && fetchComics != 2 { + tmpDir, err := os.MkdirTemp(client.config.Workdir, "fetchtmp") + if err != nil { + return err + } + defer func() { + err := os.RemoveAll(tmpDir) + if err != nil { + log.Fatal(fmt.Errorf("FetchAssetsFromAPI: remove error, path=%s, %w", tmpDir, err)) + } + }() + + client.tmpDir = tmpDir + } + + latestVersion, assets, err := client.parseMetadata(metadata, fetchComics != 1 && fetchComics != 2) + if err != nil { + return err + } + + if fetchComics != 1 && fetchComics != 2 { + if len(assets) == 0 { + log.Println("[INFO] No new assets") + return ErrNoNewAssets + } + + log.Printf("[INFO] Fetching assets, clientVersion=%s, latestVersion=%s\n", client.config.Version, latestVersion) + err = client.downloadAndExtract(assets) + if err != nil { + return err + } + + fmt.Println(latestVersion) + return nil } - log.Printf("[INFO] Fetching assets, clientVersion=%s, latestVersion=%s\n", client.config.Version, latestVersion) - err = client.downloadAndExtract(assets) + log.Printf("[INFO] Fetching comics list, type=%d, latestVersion=%s\n", fetchComics, latestVersion) + assets, err = client.fetchComicsMetadata(fetchComics-1, latestVersion) if err != nil { return err } - fmt.Println(latestVersion) - return nil + log.Printf("[INFO] Downloading comics, fileCount=%d\n", len(assets)) + _, err = client.downloadAssets(assets) + return err } diff --git a/pkg/wf/client_gen.go b/pkg/wf/client_gen.go new file mode 100644 index 0000000..dde8ca6 --- /dev/null +++ b/pkg/wf/client_gen.go @@ -0,0 +1,719 @@ +package wf + +// Code generated by github.com/tinylib/msgp DO NOT EDIT. + +import ( + "github.com/tinylib/msgp/msgp" +) + +// DecodeMsg implements msgp.Decodable +func (z *AssetListMode) DecodeMsg(dc *msgp.Reader) (err error) { + { + var zb0001 int + zb0001, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err) + return + } + (*z) = AssetListMode(zb0001) + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z AssetListMode) EncodeMsg(en *msgp.Writer) (err error) { + err = en.WriteInt(int(z)) + if err != nil { + err = msgp.WrapError(err) + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z AssetListMode) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + o = msgp.AppendInt(o, int(z)) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *AssetListMode) UnmarshalMsg(bts []byte) (o []byte, err error) { + { + var zb0001 int + zb0001, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + (*z) = AssetListMode(zb0001) + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z AssetListMode) Msgsize() (s int) { + s = msgp.IntSize + return +} + +// DecodeMsg implements msgp.Decodable +func (z *Client) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z Client) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 0 + err = en.Append(0x80) + if err != nil { + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z Client) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // map header, size 0 + o = append(o, 0x80) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *Client) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z Client) Msgsize() (s int) { + s = 1 + return +} + +// DecodeMsg implements msgp.Decodable +func (z *ClientConfig) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "Version": + z.Version, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Version") + return + } + case "Mode": + { + var zb0002 int + zb0002, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "Mode") + return + } + z.Mode = AssetListMode(zb0002) + } + case "Workdir": + z.Workdir, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Workdir") + return + } + case "Concurrency": + z.Concurrency, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "Concurrency") + return + } + case "Region": + { + var zb0003 int + zb0003, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "Region") + return + } + z.Region = ServiceRegion(zb0003) + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *ClientConfig) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 5 + // write "Version" + err = en.Append(0x85, 0xa7, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e) + if err != nil { + return + } + err = en.WriteString(z.Version) + if err != nil { + err = msgp.WrapError(err, "Version") + return + } + // write "Mode" + err = en.Append(0xa4, 0x4d, 0x6f, 0x64, 0x65) + if err != nil { + return + } + err = en.WriteInt(int(z.Mode)) + if err != nil { + err = msgp.WrapError(err, "Mode") + return + } + // write "Workdir" + err = en.Append(0xa7, 0x57, 0x6f, 0x72, 0x6b, 0x64, 0x69, 0x72) + if err != nil { + return + } + err = en.WriteString(z.Workdir) + if err != nil { + err = msgp.WrapError(err, "Workdir") + return + } + // write "Concurrency" + err = en.Append(0xab, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79) + if err != nil { + return + } + err = en.WriteInt(z.Concurrency) + if err != nil { + err = msgp.WrapError(err, "Concurrency") + return + } + // write "Region" + err = en.Append(0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) + if err != nil { + return + } + err = en.WriteInt(int(z.Region)) + if err != nil { + err = msgp.WrapError(err, "Region") + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z *ClientConfig) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // map header, size 5 + // string "Version" + o = append(o, 0x85, 0xa7, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e) + o = msgp.AppendString(o, z.Version) + // string "Mode" + o = append(o, 0xa4, 0x4d, 0x6f, 0x64, 0x65) + o = msgp.AppendInt(o, int(z.Mode)) + // string "Workdir" + o = append(o, 0xa7, 0x57, 0x6f, 0x72, 0x6b, 0x64, 0x69, 0x72) + o = msgp.AppendString(o, z.Workdir) + // string "Concurrency" + o = append(o, 0xab, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79) + o = msgp.AppendInt(o, z.Concurrency) + // string "Region" + o = append(o, 0xa6, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e) + o = msgp.AppendInt(o, int(z.Region)) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *ClientConfig) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "Version": + z.Version, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Version") + return + } + case "Mode": + { + var zb0002 int + zb0002, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Mode") + return + } + z.Mode = AssetListMode(zb0002) + } + case "Workdir": + z.Workdir, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Workdir") + return + } + case "Concurrency": + z.Concurrency, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Concurrency") + return + } + case "Region": + { + var zb0003 int + zb0003, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Region") + return + } + z.Region = ServiceRegion(zb0003) + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *ClientConfig) Msgsize() (s int) { + s = 1 + 8 + msgp.StringPrefixSize + len(z.Version) + 5 + msgp.IntSize + 8 + msgp.StringPrefixSize + len(z.Workdir) + 12 + msgp.IntSize + 7 + msgp.IntSize + return +} + +// DecodeMsg implements msgp.Decodable +func (z *ComicListRequestBody) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "page_index": + z.PageIndex, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "PageIndex") + return + } + case "kind": + z.Kind, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "Kind") + return + } + case "viewer_id": + z.ViewerID, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "ViewerID") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z ComicListRequestBody) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 3 + // write "page_index" + err = en.Append(0x83, 0xaa, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78) + if err != nil { + return + } + err = en.WriteInt(z.PageIndex) + if err != nil { + err = msgp.WrapError(err, "PageIndex") + return + } + // write "kind" + err = en.Append(0xa4, 0x6b, 0x69, 0x6e, 0x64) + if err != nil { + return + } + err = en.WriteInt(z.Kind) + if err != nil { + err = msgp.WrapError(err, "Kind") + return + } + // write "viewer_id" + err = en.Append(0xa9, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteInt(z.ViewerID) + if err != nil { + err = msgp.WrapError(err, "ViewerID") + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z ComicListRequestBody) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // map header, size 3 + // string "page_index" + o = append(o, 0x83, 0xaa, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78) + o = msgp.AppendInt(o, z.PageIndex) + // string "kind" + o = append(o, 0xa4, 0x6b, 0x69, 0x6e, 0x64) + o = msgp.AppendInt(o, z.Kind) + // string "viewer_id" + o = append(o, 0xa9, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x69, 0x64) + o = msgp.AppendInt(o, z.ViewerID) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *ComicListRequestBody) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "page_index": + z.PageIndex, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "PageIndex") + return + } + case "kind": + z.Kind, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Kind") + return + } + case "viewer_id": + z.ViewerID, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "ViewerID") + return + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z ComicListRequestBody) Msgsize() (s int) { + s = 1 + 11 + msgp.IntSize + 5 + msgp.IntSize + 10 + msgp.IntSize + return +} + +// DecodeMsg implements msgp.Decodable +func (z *ComicMetadata) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "Episode": + z.Episode, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err, "Episode") + return + } + case "Title": + z.Title, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Title") + return + } + case "CommenceTime": + z.CommenceTime, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "CommenceTime") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z ComicMetadata) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 3 + // write "Episode" + err = en.Append(0x83, 0xa7, 0x45, 0x70, 0x69, 0x73, 0x6f, 0x64, 0x65) + if err != nil { + return + } + err = en.WriteInt(z.Episode) + if err != nil { + err = msgp.WrapError(err, "Episode") + return + } + // write "Title" + err = en.Append(0xa5, 0x54, 0x69, 0x74, 0x6c, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Title) + if err != nil { + err = msgp.WrapError(err, "Title") + return + } + // write "CommenceTime" + err = en.Append(0xac, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x63, 0x65, 0x54, 0x69, 0x6d, 0x65) + if err != nil { + return + } + err = en.WriteString(z.CommenceTime) + if err != nil { + err = msgp.WrapError(err, "CommenceTime") + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z ComicMetadata) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // map header, size 3 + // string "Episode" + o = append(o, 0x83, 0xa7, 0x45, 0x70, 0x69, 0x73, 0x6f, 0x64, 0x65) + o = msgp.AppendInt(o, z.Episode) + // string "Title" + o = append(o, 0xa5, 0x54, 0x69, 0x74, 0x6c, 0x65) + o = msgp.AppendString(o, z.Title) + // string "CommenceTime" + o = append(o, 0xac, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x63, 0x65, 0x54, 0x69, 0x6d, 0x65) + o = msgp.AppendString(o, z.CommenceTime) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *ComicMetadata) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "Episode": + z.Episode, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Episode") + return + } + case "Title": + z.Title, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Title") + return + } + case "CommenceTime": + z.CommenceTime, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "CommenceTime") + return + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z ComicMetadata) Msgsize() (s int) { + s = 1 + 8 + msgp.IntSize + 6 + msgp.StringPrefixSize + len(z.Title) + 13 + msgp.StringPrefixSize + len(z.CommenceTime) + return +} + +// DecodeMsg implements msgp.Decodable +func (z *ServiceRegion) DecodeMsg(dc *msgp.Reader) (err error) { + { + var zb0001 int + zb0001, err = dc.ReadInt() + if err != nil { + err = msgp.WrapError(err) + return + } + (*z) = ServiceRegion(zb0001) + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z ServiceRegion) EncodeMsg(en *msgp.Writer) (err error) { + err = en.WriteInt(int(z)) + if err != nil { + err = msgp.WrapError(err) + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z ServiceRegion) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + o = msgp.AppendInt(o, int(z)) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *ServiceRegion) UnmarshalMsg(bts []byte) (o []byte, err error) { + { + var zb0001 int + zb0001, bts, err = msgp.ReadIntBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + (*z) = ServiceRegion(zb0001) + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z ServiceRegion) Msgsize() (s int) { + s = msgp.IntSize + return +} diff --git a/pkg/wf/client_gen_test.go b/pkg/wf/client_gen_test.go new file mode 100644 index 0000000..1187072 --- /dev/null +++ b/pkg/wf/client_gen_test.go @@ -0,0 +1,462 @@ +package wf + +// Code generated by github.com/tinylib/msgp DO NOT EDIT. + +import ( + "bytes" + "testing" + + "github.com/tinylib/msgp/msgp" +) + +func TestMarshalUnmarshalClient(t *testing.T) { + v := Client{} + bts, err := v.MarshalMsg(nil) + if err != nil { + t.Fatal(err) + } + left, err := v.UnmarshalMsg(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) + } + + left, err = msgp.Skip(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after Skip(): %q", len(left), left) + } +} + +func BenchmarkMarshalMsgClient(b *testing.B) { + v := Client{} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.MarshalMsg(nil) + } +} + +func BenchmarkAppendMsgClient(b *testing.B) { + v := Client{} + bts := make([]byte, 0, v.Msgsize()) + bts, _ = v.MarshalMsg(bts[0:0]) + b.SetBytes(int64(len(bts))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + bts, _ = v.MarshalMsg(bts[0:0]) + } +} + +func BenchmarkUnmarshalClient(b *testing.B) { + v := Client{} + bts, _ := v.MarshalMsg(nil) + b.ReportAllocs() + b.SetBytes(int64(len(bts))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := v.UnmarshalMsg(bts) + if err != nil { + b.Fatal(err) + } + } +} + +func TestEncodeDecodeClient(t *testing.T) { + v := Client{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + + m := v.Msgsize() + if buf.Len() > m { + t.Log("WARNING: TestEncodeDecodeClient Msgsize() is inaccurate") + } + + vn := Client{} + err := msgp.Decode(&buf, &vn) + if err != nil { + t.Error(err) + } + + buf.Reset() + msgp.Encode(&buf, &v) + err = msgp.NewReader(&buf).Skip() + if err != nil { + t.Error(err) + } +} + +func BenchmarkEncodeClient(b *testing.B) { + v := Client{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + en := msgp.NewWriter(msgp.Nowhere) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.EncodeMsg(en) + } + en.Flush() +} + +func BenchmarkDecodeClient(b *testing.B) { + v := Client{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + rd := msgp.NewEndlessReader(buf.Bytes(), b) + dc := msgp.NewReader(rd) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := v.DecodeMsg(dc) + if err != nil { + b.Fatal(err) + } + } +} + +func TestMarshalUnmarshalClientConfig(t *testing.T) { + v := ClientConfig{} + bts, err := v.MarshalMsg(nil) + if err != nil { + t.Fatal(err) + } + left, err := v.UnmarshalMsg(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) + } + + left, err = msgp.Skip(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after Skip(): %q", len(left), left) + } +} + +func BenchmarkMarshalMsgClientConfig(b *testing.B) { + v := ClientConfig{} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.MarshalMsg(nil) + } +} + +func BenchmarkAppendMsgClientConfig(b *testing.B) { + v := ClientConfig{} + bts := make([]byte, 0, v.Msgsize()) + bts, _ = v.MarshalMsg(bts[0:0]) + b.SetBytes(int64(len(bts))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + bts, _ = v.MarshalMsg(bts[0:0]) + } +} + +func BenchmarkUnmarshalClientConfig(b *testing.B) { + v := ClientConfig{} + bts, _ := v.MarshalMsg(nil) + b.ReportAllocs() + b.SetBytes(int64(len(bts))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := v.UnmarshalMsg(bts) + if err != nil { + b.Fatal(err) + } + } +} + +func TestEncodeDecodeClientConfig(t *testing.T) { + v := ClientConfig{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + + m := v.Msgsize() + if buf.Len() > m { + t.Log("WARNING: TestEncodeDecodeClientConfig Msgsize() is inaccurate") + } + + vn := ClientConfig{} + err := msgp.Decode(&buf, &vn) + if err != nil { + t.Error(err) + } + + buf.Reset() + msgp.Encode(&buf, &v) + err = msgp.NewReader(&buf).Skip() + if err != nil { + t.Error(err) + } +} + +func BenchmarkEncodeClientConfig(b *testing.B) { + v := ClientConfig{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + en := msgp.NewWriter(msgp.Nowhere) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.EncodeMsg(en) + } + en.Flush() +} + +func BenchmarkDecodeClientConfig(b *testing.B) { + v := ClientConfig{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + rd := msgp.NewEndlessReader(buf.Bytes(), b) + dc := msgp.NewReader(rd) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := v.DecodeMsg(dc) + if err != nil { + b.Fatal(err) + } + } +} + +func TestMarshalUnmarshalComicListRequestBody(t *testing.T) { + v := ComicListRequestBody{} + bts, err := v.MarshalMsg(nil) + if err != nil { + t.Fatal(err) + } + left, err := v.UnmarshalMsg(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) + } + + left, err = msgp.Skip(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after Skip(): %q", len(left), left) + } +} + +func BenchmarkMarshalMsgComicListRequestBody(b *testing.B) { + v := ComicListRequestBody{} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.MarshalMsg(nil) + } +} + +func BenchmarkAppendMsgComicListRequestBody(b *testing.B) { + v := ComicListRequestBody{} + bts := make([]byte, 0, v.Msgsize()) + bts, _ = v.MarshalMsg(bts[0:0]) + b.SetBytes(int64(len(bts))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + bts, _ = v.MarshalMsg(bts[0:0]) + } +} + +func BenchmarkUnmarshalComicListRequestBody(b *testing.B) { + v := ComicListRequestBody{} + bts, _ := v.MarshalMsg(nil) + b.ReportAllocs() + b.SetBytes(int64(len(bts))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := v.UnmarshalMsg(bts) + if err != nil { + b.Fatal(err) + } + } +} + +func TestEncodeDecodeComicListRequestBody(t *testing.T) { + v := ComicListRequestBody{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + + m := v.Msgsize() + if buf.Len() > m { + t.Log("WARNING: TestEncodeDecodeComicListRequestBody Msgsize() is inaccurate") + } + + vn := ComicListRequestBody{} + err := msgp.Decode(&buf, &vn) + if err != nil { + t.Error(err) + } + + buf.Reset() + msgp.Encode(&buf, &v) + err = msgp.NewReader(&buf).Skip() + if err != nil { + t.Error(err) + } +} + +func BenchmarkEncodeComicListRequestBody(b *testing.B) { + v := ComicListRequestBody{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + en := msgp.NewWriter(msgp.Nowhere) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.EncodeMsg(en) + } + en.Flush() +} + +func BenchmarkDecodeComicListRequestBody(b *testing.B) { + v := ComicListRequestBody{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + rd := msgp.NewEndlessReader(buf.Bytes(), b) + dc := msgp.NewReader(rd) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := v.DecodeMsg(dc) + if err != nil { + b.Fatal(err) + } + } +} + +func TestMarshalUnmarshalComicMetadata(t *testing.T) { + v := ComicMetadata{} + bts, err := v.MarshalMsg(nil) + if err != nil { + t.Fatal(err) + } + left, err := v.UnmarshalMsg(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) + } + + left, err = msgp.Skip(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after Skip(): %q", len(left), left) + } +} + +func BenchmarkMarshalMsgComicMetadata(b *testing.B) { + v := ComicMetadata{} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.MarshalMsg(nil) + } +} + +func BenchmarkAppendMsgComicMetadata(b *testing.B) { + v := ComicMetadata{} + bts := make([]byte, 0, v.Msgsize()) + bts, _ = v.MarshalMsg(bts[0:0]) + b.SetBytes(int64(len(bts))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + bts, _ = v.MarshalMsg(bts[0:0]) + } +} + +func BenchmarkUnmarshalComicMetadata(b *testing.B) { + v := ComicMetadata{} + bts, _ := v.MarshalMsg(nil) + b.ReportAllocs() + b.SetBytes(int64(len(bts))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := v.UnmarshalMsg(bts) + if err != nil { + b.Fatal(err) + } + } +} + +func TestEncodeDecodeComicMetadata(t *testing.T) { + v := ComicMetadata{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + + m := v.Msgsize() + if buf.Len() > m { + t.Log("WARNING: TestEncodeDecodeComicMetadata Msgsize() is inaccurate") + } + + vn := ComicMetadata{} + err := msgp.Decode(&buf, &vn) + if err != nil { + t.Error(err) + } + + buf.Reset() + msgp.Encode(&buf, &v) + err = msgp.NewReader(&buf).Skip() + if err != nil { + t.Error(err) + } +} + +func BenchmarkEncodeComicMetadata(b *testing.B) { + v := ComicMetadata{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + en := msgp.NewWriter(msgp.Nowhere) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.EncodeMsg(en) + } + en.Flush() +} + +func BenchmarkDecodeComicMetadata(b *testing.B) { + v := ComicMetadata{} + var buf bytes.Buffer + msgp.Encode(&buf, &v) + b.SetBytes(int64(buf.Len())) + rd := msgp.NewEndlessReader(buf.Bytes(), b) + dc := msgp.NewReader(rd) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := v.DecodeMsg(dc) + if err != nil { + b.Fatal(err) + } + } +}