text:
// DO NOT EDIT!
// Code generated by ffjson <https://github.com/pquerna/ffjson>
// source: json.go
// DO NOT EDIT!

package jstruct

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	fflib "github.com/pquerna/ffjson/fflib/v1"
)

func (mj *JsonOffer) MarshalJSON() ([]byte, error) {
	var buf fflib.Buffer
	if mj == nil {
		buf.WriteString("null")
		return buf.Bytes(), nil
	}
	err := mj.MarshalJSONBuf(&buf)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func (mj *JsonOffer) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
	if mj == nil {
		buf.WriteString("null")
		return nil
	}
	var err error
	var obj []byte
	_ = obj
	_ = err
	buf.WriteString(`{"numeroOffre":`)
	fflib.WriteJsonString(buf, string(mj.Id))
	buf.WriteString(`,"intitule":`)
	fflib.WriteJsonString(buf, string(mj.Title))
	buf.WriteString(`,"datePublication":`)
	fflib.WriteJsonString(buf, string(mj.Date))
	buf.WriteString(`,"salaireTexte":`)
	fflib.WriteJsonString(buf, string(mj.Salary))
	if mj.PartialTime {
		buf.WriteString(`,"tempsPartiel":true`)
	} else {
		buf.WriteString(`,"tempsPartiel":false`)
	}
	buf.WriteString(`,"lieuTexte":`)
	fflib.WriteJsonString(buf, string(mj.Location))
	buf.WriteString(`,"lieux":`)
	if mj.Locations != nil {
		buf.WriteString(`[`)
		for i, v := range mj.Locations {
			if i != 0 {
				buf.WriteString(`,`)
			}
			/* Inline struct. type=struct { Name string "json:\"libelleLieu\"" } kind=struct */
			buf.WriteString(`{ "libelleLieu":`)
			fflib.WriteJsonString(buf, string(v.Name))
			buf.WriteByte('}')
		}
		buf.WriteString(`]`)
	} else {
		buf.WriteString(`null`)
	}
	buf.WriteString(`,"texteHtml":`)
	fflib.WriteJsonString(buf, string(mj.HTML))
	buf.WriteString(`,"nomCompteEtablissement":`)
	fflib.WriteJsonString(buf, string(mj.Account))
	buf.WriteByte('}')
	return nil
}

const (
	ffj_t_JsonOfferbase = iota
	ffj_t_JsonOfferno_such_key

	ffj_t_JsonOffer_Id

	ffj_t_JsonOffer_Title

	ffj_t_JsonOffer_Date

	ffj_t_JsonOffer_Salary

	ffj_t_JsonOffer_PartialTime

	ffj_t_JsonOffer_Location

	ffj_t_JsonOffer_Locations

	ffj_t_JsonOffer_HTML

	ffj_t_JsonOffer_Account
)

var ffj_key_JsonOffer_Id = []byte("numeroOffre")

var ffj_key_JsonOffer_Title = []byte("intitule")

var ffj_key_JsonOffer_Date = []byte("datePublication")

var ffj_key_JsonOffer_Salary = []byte("salaireTexte")

var ffj_key_JsonOffer_PartialTime = []byte("tempsPartiel")

var ffj_key_JsonOffer_Location = []byte("lieuTexte")

var ffj_key_JsonOffer_Locations = []byte("lieux")

var ffj_key_JsonOffer_HTML = []byte("texteHtml")

var ffj_key_JsonOffer_Account = []byte("nomCompteEtablissement")

func (uj *JsonOffer) UnmarshalJSON(input []byte) error {
	fs := fflib.NewFFLexer(input)
	return uj.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
}

func (uj *JsonOffer) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
	var err error = nil
	currentKey := ffj_t_JsonOfferbase
	_ = currentKey
	tok := fflib.FFTok_init
	wantedTok := fflib.FFTok_init

mainparse:
	for {
		tok = fs.Scan()
		//	println(fmt.Sprintf("debug: tok: %v  state: %v", tok, state))
		if tok == fflib.FFTok_error {
			goto tokerror
		}

		switch state {

		case fflib.FFParse_map_start:
			if tok != fflib.FFTok_left_bracket {
				wantedTok = fflib.FFTok_left_bracket
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_key
			continue

		case fflib.FFParse_after_value:
			if tok == fflib.FFTok_comma {
				state = fflib.FFParse_want_key
			} else if tok == fflib.FFTok_right_bracket {
				goto done
			} else {
				wantedTok = fflib.FFTok_comma
				goto wrongtokenerror
			}

		case fflib.FFParse_want_key:
			// json {} ended. goto exit. woo.
			if tok == fflib.FFTok_right_bracket {
				goto done
			}
			if tok != fflib.FFTok_string {
				wantedTok = fflib.FFTok_string
				goto wrongtokenerror
			}

			kn := fs.Output.Bytes()
			if len(kn) <= 0 {
				// "" case. hrm.
				currentKey = ffj_t_JsonOfferno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			} else {
				switch kn[0] {

				case 'd':

					if bytes.Equal(ffj_key_JsonOffer_Date, kn) {
						currentKey = ffj_t_JsonOffer_Date
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 'i':

					if bytes.Equal(ffj_key_JsonOffer_Title, kn) {
						currentKey = ffj_t_JsonOffer_Title
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 'l':

					if bytes.Equal(ffj_key_JsonOffer_Location, kn) {
						currentKey = ffj_t_JsonOffer_Location
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_JsonOffer_Locations, kn) {
						currentKey = ffj_t_JsonOffer_Locations
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 'n':

					if bytes.Equal(ffj_key_JsonOffer_Id, kn) {
						currentKey = ffj_t_JsonOffer_Id
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_JsonOffer_Account, kn) {
						currentKey = ffj_t_JsonOffer_Account
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 's':

					if bytes.Equal(ffj_key_JsonOffer_Salary, kn) {
						currentKey = ffj_t_JsonOffer_Salary
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 't':

					if bytes.Equal(ffj_key_JsonOffer_PartialTime, kn) {
						currentKey = ffj_t_JsonOffer_PartialTime
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_JsonOffer_HTML, kn) {
						currentKey = ffj_t_JsonOffer_HTML
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				}

				if fflib.EqualFoldRight(ffj_key_JsonOffer_Account, kn) {
					currentKey = ffj_t_JsonOffer_Account
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_JsonOffer_HTML, kn) {
					currentKey = ffj_t_JsonOffer_HTML
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_JsonOffer_Locations, kn) {
					currentKey = ffj_t_JsonOffer_Locations
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_JsonOffer_Location, kn) {
					currentKey = ffj_t_JsonOffer_Location
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.EqualFoldRight(ffj_key_JsonOffer_PartialTime, kn) {
					currentKey = ffj_t_JsonOffer_PartialTime
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.EqualFoldRight(ffj_key_JsonOffer_Salary, kn) {
					currentKey = ffj_t_JsonOffer_Salary
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_JsonOffer_Date, kn) {
					currentKey = ffj_t_JsonOffer_Date
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_JsonOffer_Title, kn) {
					currentKey = ffj_t_JsonOffer_Title
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_JsonOffer_Id, kn) {
					currentKey = ffj_t_JsonOffer_Id
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				currentKey = ffj_t_JsonOfferno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			}

		case fflib.FFParse_want_colon:
			if tok != fflib.FFTok_colon {
				wantedTok = fflib.FFTok_colon
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_value
			continue
		case fflib.FFParse_want_value:

			if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
				switch currentKey {

				case ffj_t_JsonOffer_Id:
					goto handle_Id

				case ffj_t_JsonOffer_Title:
					goto handle_Title

				case ffj_t_JsonOffer_Date:
					goto handle_Date

				case ffj_t_JsonOffer_Salary:
					goto handle_Salary

				case ffj_t_JsonOffer_PartialTime:
					goto handle_PartialTime

				case ffj_t_JsonOffer_Location:
					goto handle_Location

				case ffj_t_JsonOffer_Locations:
					goto handle_Locations

				case ffj_t_JsonOffer_HTML:
					goto handle_HTML

				case ffj_t_JsonOffer_Account:
					goto handle_Account

				case ffj_t_JsonOfferno_such_key:
					err = fs.SkipField(tok)
					if err != nil {
						return fs.WrapErr(err)
					}
					state = fflib.FFParse_after_value
					goto mainparse
				}
			} else {
				goto wantedvalue
			}
		}
	}

handle_Id:

	/* handler: uj.Id type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.Id = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Title:

	/* handler: uj.Title type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.Title = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Date:

	/* handler: uj.Date type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.Date = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Salary:

	/* handler: uj.Salary type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.Salary = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_PartialTime:

	/* handler: uj.PartialTime type=bool kind=bool quoted=false*/

	{
		if tok != fflib.FFTok_bool && tok != fflib.FFTok_null {
			return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for bool", tok))
		}
	}

	{
		if tok == fflib.FFTok_null {

		} else {
			tmpb := fs.Output.Bytes()

			if bytes.Compare([]byte{'t', 'r', 'u', 'e'}, tmpb) == 0 {

				uj.PartialTime = true

			} else if bytes.Compare([]byte{'f', 'a', 'l', 's', 'e'}, tmpb) == 0 {

				uj.PartialTime = false

			} else {
				err = errors.New("unexpected bytes for true/false value")
				return fs.WrapErr(err)
			}

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Location:

	/* handler: uj.Location type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.Location = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Locations:

	/* handler: uj.Locations type=[]struct { Name string "json:\"libelleLieu\"" } kind=slice quoted=false*/

	{
		/* Falling back. type=[]struct { Name string "json:\"libelleLieu\"" } kind=slice */
		tbuf, err := fs.CaptureField(tok)
		if err != nil {
			return fs.WrapErr(err)
		}

		err = json.Unmarshal(tbuf, &uj.Locations)
		if err != nil {
			return fs.WrapErr(err)
		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_HTML:

	/* handler: uj.HTML type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.HTML = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Account:

	/* handler: uj.Account type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.Account = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

wantedvalue:
	return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
wrongtokenerror:
	return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
tokerror:
	if fs.BigError != nil {
		return fs.WrapErr(fs.BigError)
	}
	err = fs.Error.ToError()
	if err != nil {
		return fs.WrapErr(err)
	}
	panic("ffjson-generated: unreachable, please report bug.")
done:
	return nil
}

func (mj *LocComponent) MarshalJSON() ([]byte, error) {
	var buf fflib.Buffer
	if mj == nil {
		buf.WriteString("null")
		return buf.Bytes(), nil
	}
	err := mj.MarshalJSONBuf(&buf)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func (mj *LocComponent) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
	if mj == nil {
		buf.WriteString("null")
		return nil
	}
	var err error
	var obj []byte
	_ = obj
	_ = err
	buf.WriteString(`{"city":`)
	fflib.WriteJsonString(buf, string(mj.City))
	buf.WriteString(`,"postcode":`)
	fflib.WriteJsonString(buf, string(mj.PostCode))
	buf.WriteString(`,"county":`)
	fflib.WriteJsonString(buf, string(mj.County))
	buf.WriteString(`,"state":`)
	fflib.WriteJsonString(buf, string(mj.State))
	buf.WriteString(`,"country":`)
	fflib.WriteJsonString(buf, string(mj.Country))
	buf.WriteString(`,"country_code":`)
	fflib.WriteJsonString(buf, string(mj.CountryCode))
	buf.WriteByte('}')
	return nil
}

const (
	ffj_t_LocComponentbase = iota
	ffj_t_LocComponentno_such_key

	ffj_t_LocComponent_City

	ffj_t_LocComponent_PostCode

	ffj_t_LocComponent_County

	ffj_t_LocComponent_State

	ffj_t_LocComponent_Country

	ffj_t_LocComponent_CountryCode
)

var ffj_key_LocComponent_City = []byte("city")

var ffj_key_LocComponent_PostCode = []byte("postcode")

var ffj_key_LocComponent_County = []byte("county")

var ffj_key_LocComponent_State = []byte("state")

var ffj_key_LocComponent_Country = []byte("country")

var ffj_key_LocComponent_CountryCode = []byte("country_code")

func (uj *LocComponent) UnmarshalJSON(input []byte) error {
	fs := fflib.NewFFLexer(input)
	return uj.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
}

func (uj *LocComponent) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
	var err error = nil
	currentKey := ffj_t_LocComponentbase
	_ = currentKey
	tok := fflib.FFTok_init
	wantedTok := fflib.FFTok_init

mainparse:
	for {
		tok = fs.Scan()
		//	println(fmt.Sprintf("debug: tok: %v  state: %v", tok, state))
		if tok == fflib.FFTok_error {
			goto tokerror
		}

		switch state {

		case fflib.FFParse_map_start:
			if tok != fflib.FFTok_left_bracket {
				wantedTok = fflib.FFTok_left_bracket
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_key
			continue

		case fflib.FFParse_after_value:
			if tok == fflib.FFTok_comma {
				state = fflib.FFParse_want_key
			} else if tok == fflib.FFTok_right_bracket {
				goto done
			} else {
				wantedTok = fflib.FFTok_comma
				goto wrongtokenerror
			}

		case fflib.FFParse_want_key:
			// json {} ended. goto exit. woo.
			if tok == fflib.FFTok_right_bracket {
				goto done
			}
			if tok != fflib.FFTok_string {
				wantedTok = fflib.FFTok_string
				goto wrongtokenerror
			}

			kn := fs.Output.Bytes()
			if len(kn) <= 0 {
				// "" case. hrm.
				currentKey = ffj_t_LocComponentno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			} else {
				switch kn[0] {

				case 'c':

					if bytes.Equal(ffj_key_LocComponent_City, kn) {
						currentKey = ffj_t_LocComponent_City
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_LocComponent_County, kn) {
						currentKey = ffj_t_LocComponent_County
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_LocComponent_Country, kn) {
						currentKey = ffj_t_LocComponent_Country
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_LocComponent_CountryCode, kn) {
						currentKey = ffj_t_LocComponent_CountryCode
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 'p':

					if bytes.Equal(ffj_key_LocComponent_PostCode, kn) {
						currentKey = ffj_t_LocComponent_PostCode
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 's':

					if bytes.Equal(ffj_key_LocComponent_State, kn) {
						currentKey = ffj_t_LocComponent_State
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				}

				if fflib.AsciiEqualFold(ffj_key_LocComponent_CountryCode, kn) {
					currentKey = ffj_t_LocComponent_CountryCode
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocComponent_Country, kn) {
					currentKey = ffj_t_LocComponent_Country
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.EqualFoldRight(ffj_key_LocComponent_State, kn) {
					currentKey = ffj_t_LocComponent_State
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocComponent_County, kn) {
					currentKey = ffj_t_LocComponent_County
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.EqualFoldRight(ffj_key_LocComponent_PostCode, kn) {
					currentKey = ffj_t_LocComponent_PostCode
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocComponent_City, kn) {
					currentKey = ffj_t_LocComponent_City
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				currentKey = ffj_t_LocComponentno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			}

		case fflib.FFParse_want_colon:
			if tok != fflib.FFTok_colon {
				wantedTok = fflib.FFTok_colon
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_value
			continue
		case fflib.FFParse_want_value:

			if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
				switch currentKey {

				case ffj_t_LocComponent_City:
					goto handle_City

				case ffj_t_LocComponent_PostCode:
					goto handle_PostCode

				case ffj_t_LocComponent_County:
					goto handle_County

				case ffj_t_LocComponent_State:
					goto handle_State

				case ffj_t_LocComponent_Country:
					goto handle_Country

				case ffj_t_LocComponent_CountryCode:
					goto handle_CountryCode

				case ffj_t_LocComponentno_such_key:
					err = fs.SkipField(tok)
					if err != nil {
						return fs.WrapErr(err)
					}
					state = fflib.FFParse_after_value
					goto mainparse
				}
			} else {
				goto wantedvalue
			}
		}
	}

handle_City:

	/* handler: uj.City type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.City = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_PostCode:

	/* handler: uj.PostCode type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.PostCode = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_County:

	/* handler: uj.County type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.County = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_State:

	/* handler: uj.State type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.State = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Country:

	/* handler: uj.Country type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.Country = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_CountryCode:

	/* handler: uj.CountryCode type=string kind=string quoted=false*/

	{

		{
			if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
			}
		}

		if tok == fflib.FFTok_null {

		} else {

			outBuf := fs.Output.Bytes()

			uj.CountryCode = string(string(outBuf))

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

wantedvalue:
	return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
wrongtokenerror:
	return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
tokerror:
	if fs.BigError != nil {
		return fs.WrapErr(fs.BigError)
	}
	err = fs.Error.ToError()
	if err != nil {
		return fs.WrapErr(err)
	}
	panic("ffjson-generated: unreachable, please report bug.")
done:
	return nil
}

func (mj *LocGeom) MarshalJSON() ([]byte, error) {
	var buf fflib.Buffer
	if mj == nil {
		buf.WriteString("null")
		return buf.Bytes(), nil
	}
	err := mj.MarshalJSONBuf(&buf)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func (mj *LocGeom) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
	if mj == nil {
		buf.WriteString("null")
		return nil
	}
	var err error
	var obj []byte
	_ = obj
	_ = err
	buf.WriteString(`{"lat":`)
	fflib.AppendFloat(buf, float64(mj.Lat), 'g', -1, 64)
	buf.WriteString(`,"lng":`)
	fflib.AppendFloat(buf, float64(mj.Lon), 'g', -1, 64)
	buf.WriteByte('}')
	return nil
}

const (
	ffj_t_LocGeombase = iota
	ffj_t_LocGeomno_such_key

	ffj_t_LocGeom_Lat

	ffj_t_LocGeom_Lon
)

var ffj_key_LocGeom_Lat = []byte("lat")

var ffj_key_LocGeom_Lon = []byte("lng")

func (uj *LocGeom) UnmarshalJSON(input []byte) error {
	fs := fflib.NewFFLexer(input)
	return uj.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
}

func (uj *LocGeom) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
	var err error = nil
	currentKey := ffj_t_LocGeombase
	_ = currentKey
	tok := fflib.FFTok_init
	wantedTok := fflib.FFTok_init

mainparse:
	for {
		tok = fs.Scan()
		//	println(fmt.Sprintf("debug: tok: %v  state: %v", tok, state))
		if tok == fflib.FFTok_error {
			goto tokerror
		}

		switch state {

		case fflib.FFParse_map_start:
			if tok != fflib.FFTok_left_bracket {
				wantedTok = fflib.FFTok_left_bracket
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_key
			continue

		case fflib.FFParse_after_value:
			if tok == fflib.FFTok_comma {
				state = fflib.FFParse_want_key
			} else if tok == fflib.FFTok_right_bracket {
				goto done
			} else {
				wantedTok = fflib.FFTok_comma
				goto wrongtokenerror
			}

		case fflib.FFParse_want_key:
			// json {} ended. goto exit. woo.
			if tok == fflib.FFTok_right_bracket {
				goto done
			}
			if tok != fflib.FFTok_string {
				wantedTok = fflib.FFTok_string
				goto wrongtokenerror
			}

			kn := fs.Output.Bytes()
			if len(kn) <= 0 {
				// "" case. hrm.
				currentKey = ffj_t_LocGeomno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			} else {
				switch kn[0] {

				case 'l':

					if bytes.Equal(ffj_key_LocGeom_Lat, kn) {
						currentKey = ffj_t_LocGeom_Lat
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_LocGeom_Lon, kn) {
						currentKey = ffj_t_LocGeom_Lon
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocGeom_Lon, kn) {
					currentKey = ffj_t_LocGeom_Lon
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocGeom_Lat, kn) {
					currentKey = ffj_t_LocGeom_Lat
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				currentKey = ffj_t_LocGeomno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			}

		case fflib.FFParse_want_colon:
			if tok != fflib.FFTok_colon {
				wantedTok = fflib.FFTok_colon
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_value
			continue
		case fflib.FFParse_want_value:

			if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
				switch currentKey {

				case ffj_t_LocGeom_Lat:
					goto handle_Lat

				case ffj_t_LocGeom_Lon:
					goto handle_Lon

				case ffj_t_LocGeomno_such_key:
					err = fs.SkipField(tok)
					if err != nil {
						return fs.WrapErr(err)
					}
					state = fflib.FFParse_after_value
					goto mainparse
				}
			} else {
				goto wantedvalue
			}
		}
	}

handle_Lat:

	/* handler: uj.Lat type=float64 kind=float64 quoted=false*/

	{
		if tok != fflib.FFTok_double && tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
			return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for float64", tok))
		}
	}

	{

		if tok == fflib.FFTok_null {

		} else {

			tval, err := fflib.ParseFloat(fs.Output.Bytes(), 64)

			if err != nil {
				return fs.WrapErr(err)
			}

			uj.Lat = float64(tval)

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Lon:

	/* handler: uj.Lon type=float64 kind=float64 quoted=false*/

	{
		if tok != fflib.FFTok_double && tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
			return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for float64", tok))
		}
	}

	{

		if tok == fflib.FFTok_null {

		} else {

			tval, err := fflib.ParseFloat(fs.Output.Bytes(), 64)

			if err != nil {
				return fs.WrapErr(err)
			}

			uj.Lon = float64(tval)

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

wantedvalue:
	return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
wrongtokenerror:
	return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
tokerror:
	if fs.BigError != nil {
		return fs.WrapErr(fs.BigError)
	}
	err = fs.Error.ToError()
	if err != nil {
		return fs.WrapErr(err)
	}
	panic("ffjson-generated: unreachable, please report bug.")
done:
	return nil
}

func (mj *LocRate) MarshalJSON() ([]byte, error) {
	var buf fflib.Buffer
	if mj == nil {
		buf.WriteString("null")
		return buf.Bytes(), nil
	}
	err := mj.MarshalJSONBuf(&buf)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func (mj *LocRate) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
	if mj == nil {
		buf.WriteString("null")
		return nil
	}
	var err error
	var obj []byte
	_ = obj
	_ = err
	buf.WriteString(`{"limit":`)
	fflib.FormatBits2(buf, uint64(mj.Limit), 10, mj.Limit < 0)
	buf.WriteString(`,"remaining":`)
	fflib.FormatBits2(buf, uint64(mj.Remaining), 10, mj.Remaining < 0)
	buf.WriteByte('}')
	return nil
}

const (
	ffj_t_LocRatebase = iota
	ffj_t_LocRateno_such_key

	ffj_t_LocRate_Limit

	ffj_t_LocRate_Remaining
)

var ffj_key_LocRate_Limit = []byte("limit")

var ffj_key_LocRate_Remaining = []byte("remaining")

func (uj *LocRate) UnmarshalJSON(input []byte) error {
	fs := fflib.NewFFLexer(input)
	return uj.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
}

func (uj *LocRate) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
	var err error = nil
	currentKey := ffj_t_LocRatebase
	_ = currentKey
	tok := fflib.FFTok_init
	wantedTok := fflib.FFTok_init

mainparse:
	for {
		tok = fs.Scan()
		//	println(fmt.Sprintf("debug: tok: %v  state: %v", tok, state))
		if tok == fflib.FFTok_error {
			goto tokerror
		}

		switch state {

		case fflib.FFParse_map_start:
			if tok != fflib.FFTok_left_bracket {
				wantedTok = fflib.FFTok_left_bracket
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_key
			continue

		case fflib.FFParse_after_value:
			if tok == fflib.FFTok_comma {
				state = fflib.FFParse_want_key
			} else if tok == fflib.FFTok_right_bracket {
				goto done
			} else {
				wantedTok = fflib.FFTok_comma
				goto wrongtokenerror
			}

		case fflib.FFParse_want_key:
			// json {} ended. goto exit. woo.
			if tok == fflib.FFTok_right_bracket {
				goto done
			}
			if tok != fflib.FFTok_string {
				wantedTok = fflib.FFTok_string
				goto wrongtokenerror
			}

			kn := fs.Output.Bytes()
			if len(kn) <= 0 {
				// "" case. hrm.
				currentKey = ffj_t_LocRateno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			} else {
				switch kn[0] {

				case 'l':

					if bytes.Equal(ffj_key_LocRate_Limit, kn) {
						currentKey = ffj_t_LocRate_Limit
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 'r':

					if bytes.Equal(ffj_key_LocRate_Remaining, kn) {
						currentKey = ffj_t_LocRate_Remaining
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocRate_Remaining, kn) {
					currentKey = ffj_t_LocRate_Remaining
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocRate_Limit, kn) {
					currentKey = ffj_t_LocRate_Limit
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				currentKey = ffj_t_LocRateno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			}

		case fflib.FFParse_want_colon:
			if tok != fflib.FFTok_colon {
				wantedTok = fflib.FFTok_colon
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_value
			continue
		case fflib.FFParse_want_value:

			if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
				switch currentKey {

				case ffj_t_LocRate_Limit:
					goto handle_Limit

				case ffj_t_LocRate_Remaining:
					goto handle_Remaining

				case ffj_t_LocRateno_such_key:
					err = fs.SkipField(tok)
					if err != nil {
						return fs.WrapErr(err)
					}
					state = fflib.FFParse_after_value
					goto mainparse
				}
			} else {
				goto wantedvalue
			}
		}
	}

handle_Limit:

	/* handler: uj.Limit type=int kind=int quoted=false*/

	{
		if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
			return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
		}
	}

	{

		if tok == fflib.FFTok_null {

		} else {

			tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)

			if err != nil {
				return fs.WrapErr(err)
			}

			uj.Limit = int(tval)

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Remaining:

	/* handler: uj.Remaining type=int kind=int quoted=false*/

	{
		if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
			return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
		}
	}

	{

		if tok == fflib.FFTok_null {

		} else {

			tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)

			if err != nil {
				return fs.WrapErr(err)
			}

			uj.Remaining = int(tval)

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

wantedvalue:
	return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
wrongtokenerror:
	return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
tokerror:
	if fs.BigError != nil {
		return fs.WrapErr(fs.BigError)
	}
	err = fs.Error.ToError()
	if err != nil {
		return fs.WrapErr(err)
	}
	panic("ffjson-generated: unreachable, please report bug.")
done:
	return nil
}

func (mj *LocResult) MarshalJSON() ([]byte, error) {
	var buf fflib.Buffer
	if mj == nil {
		buf.WriteString("null")
		return buf.Bytes(), nil
	}
	err := mj.MarshalJSONBuf(&buf)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func (mj *LocResult) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
	if mj == nil {
		buf.WriteString("null")
		return nil
	}
	var err error
	var obj []byte
	_ = obj
	_ = err
	buf.WriteString(`{"components":`)

	{

		err = mj.Component.MarshalJSONBuf(buf)
		if err != nil {
			return err
		}

	}
	if mj.Geometry != nil {
		buf.WriteString(`,"geometry":`)

		{

			err = mj.Geometry.MarshalJSONBuf(buf)
			if err != nil {
				return err
			}

		}
	} else {
		buf.WriteString(`,"geometry":null`)
	}
	buf.WriteByte('}')
	return nil
}

const (
	ffj_t_LocResultbase = iota
	ffj_t_LocResultno_such_key

	ffj_t_LocResult_Component

	ffj_t_LocResult_Geometry
)

var ffj_key_LocResult_Component = []byte("components")

var ffj_key_LocResult_Geometry = []byte("geometry")

func (uj *LocResult) UnmarshalJSON(input []byte) error {
	fs := fflib.NewFFLexer(input)
	return uj.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
}

func (uj *LocResult) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
	var err error = nil
	currentKey := ffj_t_LocResultbase
	_ = currentKey
	tok := fflib.FFTok_init
	wantedTok := fflib.FFTok_init

mainparse:
	for {
		tok = fs.Scan()
		//	println(fmt.Sprintf("debug: tok: %v  state: %v", tok, state))
		if tok == fflib.FFTok_error {
			goto tokerror
		}

		switch state {

		case fflib.FFParse_map_start:
			if tok != fflib.FFTok_left_bracket {
				wantedTok = fflib.FFTok_left_bracket
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_key
			continue

		case fflib.FFParse_after_value:
			if tok == fflib.FFTok_comma {
				state = fflib.FFParse_want_key
			} else if tok == fflib.FFTok_right_bracket {
				goto done
			} else {
				wantedTok = fflib.FFTok_comma
				goto wrongtokenerror
			}

		case fflib.FFParse_want_key:
			// json {} ended. goto exit. woo.
			if tok == fflib.FFTok_right_bracket {
				goto done
			}
			if tok != fflib.FFTok_string {
				wantedTok = fflib.FFTok_string
				goto wrongtokenerror
			}

			kn := fs.Output.Bytes()
			if len(kn) <= 0 {
				// "" case. hrm.
				currentKey = ffj_t_LocResultno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			} else {
				switch kn[0] {

				case 'c':

					if bytes.Equal(ffj_key_LocResult_Component, kn) {
						currentKey = ffj_t_LocResult_Component
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 'g':

					if bytes.Equal(ffj_key_LocResult_Geometry, kn) {
						currentKey = ffj_t_LocResult_Geometry
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				}

				if fflib.SimpleLetterEqualFold(ffj_key_LocResult_Geometry, kn) {
					currentKey = ffj_t_LocResult_Geometry
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.EqualFoldRight(ffj_key_LocResult_Component, kn) {
					currentKey = ffj_t_LocResult_Component
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				currentKey = ffj_t_LocResultno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			}

		case fflib.FFParse_want_colon:
			if tok != fflib.FFTok_colon {
				wantedTok = fflib.FFTok_colon
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_value
			continue
		case fflib.FFParse_want_value:

			if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
				switch currentKey {

				case ffj_t_LocResult_Component:
					goto handle_Component

				case ffj_t_LocResult_Geometry:
					goto handle_Geometry

				case ffj_t_LocResultno_such_key:
					err = fs.SkipField(tok)
					if err != nil {
						return fs.WrapErr(err)
					}
					state = fflib.FFParse_after_value
					goto mainparse
				}
			} else {
				goto wantedvalue
			}
		}
	}

handle_Component:

	/* handler: uj.Component type=jstruct.LocComponent kind=struct quoted=false*/

	{
		if tok == fflib.FFTok_null {

			state = fflib.FFParse_after_value
			goto mainparse
		}

		err = uj.Component.UnmarshalJSONFFLexer(fs, fflib.FFParse_want_key)
		if err != nil {
			return err
		}
		state = fflib.FFParse_after_value
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Geometry:

	/* handler: uj.Geometry type=jstruct.LocGeom kind=struct quoted=false*/

	{
		if tok == fflib.FFTok_null {

			uj.Geometry = nil

			state = fflib.FFParse_after_value
			goto mainparse
		}

		if uj.Geometry == nil {
			uj.Geometry = new(LocGeom)
		}

		err = uj.Geometry.UnmarshalJSONFFLexer(fs, fflib.FFParse_want_key)
		if err != nil {
			return err
		}
		state = fflib.FFParse_after_value
	}

	state = fflib.FFParse_after_value
	goto mainparse

wantedvalue:
	return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
wrongtokenerror:
	return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
tokerror:
	if fs.BigError != nil {
		return fs.WrapErr(fs.BigError)
	}
	err = fs.Error.ToError()
	if err != nil {
		return fs.WrapErr(err)
	}
	panic("ffjson-generated: unreachable, please report bug.")
done:
	return nil
}

func (mj *Location) MarshalJSON() ([]byte, error) {
	var buf fflib.Buffer
	if mj == nil {
		buf.WriteString("null")
		return buf.Bytes(), nil
	}
	err := mj.MarshalJSONBuf(&buf)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func (mj *Location) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
	if mj == nil {
		buf.WriteString("null")
		return nil
	}
	var err error
	var obj []byte
	_ = obj
	_ = err
	if mj.Cached {
		buf.WriteString(`{"Cached":true`)
	} else {
		buf.WriteString(`{"Cached":false`)
	}
	buf.WriteString(`,"rate":`)

	{

		err = mj.Rate.MarshalJSONBuf(buf)
		if err != nil {
			return err
		}

	}
	buf.WriteString(`,"results":`)
	if mj.Results != nil {
		buf.WriteString(`[`)
		for i, v := range mj.Results {
			if i != 0 {
				buf.WriteString(`,`)
			}

			{

				err = v.MarshalJSONBuf(buf)
				if err != nil {
					return err
				}

			}
		}
		buf.WriteString(`]`)
	} else {
		buf.WriteString(`null`)
	}
	buf.WriteByte('}')
	return nil
}

const (
	ffj_t_Locationbase = iota
	ffj_t_Locationno_such_key

	ffj_t_Location_Cached

	ffj_t_Location_Rate

	ffj_t_Location_Results
)

var ffj_key_Location_Cached = []byte("Cached")

var ffj_key_Location_Rate = []byte("rate")

var ffj_key_Location_Results = []byte("results")

func (uj *Location) UnmarshalJSON(input []byte) error {
	fs := fflib.NewFFLexer(input)
	return uj.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
}

func (uj *Location) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
	var err error = nil
	currentKey := ffj_t_Locationbase
	_ = currentKey
	tok := fflib.FFTok_init
	wantedTok := fflib.FFTok_init

mainparse:
	for {
		tok = fs.Scan()
		//	println(fmt.Sprintf("debug: tok: %v  state: %v", tok, state))
		if tok == fflib.FFTok_error {
			goto tokerror
		}

		switch state {

		case fflib.FFParse_map_start:
			if tok != fflib.FFTok_left_bracket {
				wantedTok = fflib.FFTok_left_bracket
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_key
			continue

		case fflib.FFParse_after_value:
			if tok == fflib.FFTok_comma {
				state = fflib.FFParse_want_key
			} else if tok == fflib.FFTok_right_bracket {
				goto done
			} else {
				wantedTok = fflib.FFTok_comma
				goto wrongtokenerror
			}

		case fflib.FFParse_want_key:
			// json {} ended. goto exit. woo.
			if tok == fflib.FFTok_right_bracket {
				goto done
			}
			if tok != fflib.FFTok_string {
				wantedTok = fflib.FFTok_string
				goto wrongtokenerror
			}

			kn := fs.Output.Bytes()
			if len(kn) <= 0 {
				// "" case. hrm.
				currentKey = ffj_t_Locationno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			} else {
				switch kn[0] {

				case 'C':

					if bytes.Equal(ffj_key_Location_Cached, kn) {
						currentKey = ffj_t_Location_Cached
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				case 'r':

					if bytes.Equal(ffj_key_Location_Rate, kn) {
						currentKey = ffj_t_Location_Rate
						state = fflib.FFParse_want_colon
						goto mainparse

					} else if bytes.Equal(ffj_key_Location_Results, kn) {
						currentKey = ffj_t_Location_Results
						state = fflib.FFParse_want_colon
						goto mainparse
					}

				}

				if fflib.EqualFoldRight(ffj_key_Location_Results, kn) {
					currentKey = ffj_t_Location_Results
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_Location_Rate, kn) {
					currentKey = ffj_t_Location_Rate
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				if fflib.SimpleLetterEqualFold(ffj_key_Location_Cached, kn) {
					currentKey = ffj_t_Location_Cached
					state = fflib.FFParse_want_colon
					goto mainparse
				}

				currentKey = ffj_t_Locationno_such_key
				state = fflib.FFParse_want_colon
				goto mainparse
			}

		case fflib.FFParse_want_colon:
			if tok != fflib.FFTok_colon {
				wantedTok = fflib.FFTok_colon
				goto wrongtokenerror
			}
			state = fflib.FFParse_want_value
			continue
		case fflib.FFParse_want_value:

			if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
				switch currentKey {

				case ffj_t_Location_Cached:
					goto handle_Cached

				case ffj_t_Location_Rate:
					goto handle_Rate

				case ffj_t_Location_Results:
					goto handle_Results

				case ffj_t_Locationno_such_key:
					err = fs.SkipField(tok)
					if err != nil {
						return fs.WrapErr(err)
					}
					state = fflib.FFParse_after_value
					goto mainparse
				}
			} else {
				goto wantedvalue
			}
		}
	}

handle_Cached:

	/* handler: uj.Cached type=bool kind=bool quoted=false*/

	{
		if tok != fflib.FFTok_bool && tok != fflib.FFTok_null {
			return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for bool", tok))
		}
	}

	{
		if tok == fflib.FFTok_null {

		} else {
			tmpb := fs.Output.Bytes()

			if bytes.Compare([]byte{'t', 'r', 'u', 'e'}, tmpb) == 0 {

				uj.Cached = true

			} else if bytes.Compare([]byte{'f', 'a', 'l', 's', 'e'}, tmpb) == 0 {

				uj.Cached = false

			} else {
				err = errors.New("unexpected bytes for true/false value")
				return fs.WrapErr(err)
			}

		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Rate:

	/* handler: uj.Rate type=jstruct.LocRate kind=struct quoted=false*/

	{
		if tok == fflib.FFTok_null {

			state = fflib.FFParse_after_value
			goto mainparse
		}

		err = uj.Rate.UnmarshalJSONFFLexer(fs, fflib.FFParse_want_key)
		if err != nil {
			return err
		}
		state = fflib.FFParse_after_value
	}

	state = fflib.FFParse_after_value
	goto mainparse

handle_Results:

	/* handler: uj.Results type=[]jstruct.LocResult kind=slice quoted=false*/

	{

		{
			if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
				return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
			}
		}

		if tok == fflib.FFTok_null {
			uj.Results = nil
		} else {

			uj.Results = make([]LocResult, 0)

			wantVal := true

			for {

				var tmp_uj__Results LocResult

				tok = fs.Scan()
				if tok == fflib.FFTok_error {
					goto tokerror
				}
				if tok == fflib.FFTok_right_brace {
					break
				}

				if tok == fflib.FFTok_comma {
					if wantVal == true {
						// TODO(pquerna): this isn't an ideal error message, this handles
						// things like [,,,] as an array value.
						return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
					}
					continue
				} else {
					wantVal = true
				}

				/* handler: tmp_uj__Results type=jstruct.LocResult kind=struct quoted=false*/

				{
					if tok == fflib.FFTok_null {

						state = fflib.FFParse_after_value
						goto mainparse
					}

					err = tmp_uj__Results.UnmarshalJSONFFLexer(fs, fflib.FFParse_want_key)
					if err != nil {
						return err
					}
					state = fflib.FFParse_after_value
				}

				uj.Results = append(uj.Results, tmp_uj__Results)
				wantVal = false
			}
		}
	}

	state = fflib.FFParse_after_value
	goto mainparse

wantedvalue:
	return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
wrongtokenerror:
	return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
tokerror:
	if fs.BigError != nil {
		return fs.WrapErr(fs.BigError)
	}
	err = fs.Error.ToError()
	if err != nil {
		return fs.WrapErr(err)
	}
	panic("ffjson-generated: unreachable, please report bug.")
done:
	return nil
}


The General Switch Management Protocol (GSMP), is a general purpose protocol to control an ATM switch. GSMP allows a controller to establish and release connections across the switch; add and delete leaves on a point-to-multipoint connection; manage switch ports; request configuration information; and request statistics.
The General Switch Management Protocol (GSMP), is a general purpose protocol to control an ATM switch. GSMP allows a controller to establish and release connections across the switch; add and delete leaves on a point-to-multipoint connection; manage switch ports; request configuration information; and request statistics. It also allows the switch to inform the controller of asynchronous events such as a link going down. GSMP runs across an ATM link connecting the controller to the switch, on a control connection (virtual channel) established at initialization. The GSMP protocol is asymmetric, the controller being the master and the switch being the slave. Multiple switches may be controlled by a single controller using multiple instantiations of the protocol over separate control connections.
A switch is assumed to contain multiple "ports". Each port is a combination of one "input port" and one "output port". Some GSMP requests refer to the port as a whole whereas other requests are specific to the input port or the output port. ATM cells arrive at the switch from an external communication link on incoming virtual channels at an input port. ATM cells depart from the switch to an external communication link on outgoing virtual channels from an output port. Virtual channels on a port or link are referenced by their virtual path and virtual channel identifiers (VPI/VCI). A virtual channel connection across a switch is formed by connecting an incoming virtual channel to one or more outgoing virtual channels. Virtual channel connections are referenced by the input port on which they arrive and the virtual path and virtual channel identifiers (VPI/VCI) of their incoming virtual channel.
In general a virtual channel is established with a certain quality of service (QOS). Unfortunately this is an ill defined and changing concept as new ideas make their way into hardware. For this version of the GSMP protocol it is assumed that each virtual channel connection may be assigned a priority when it is established. It may be assumed that for virtual channel connections that share the same output port, an ATM cell on a connection with a higher priority is much more likely to exit the switch before an ATM cell on a connection with a lower priority if they are both in the switch at the same time. The number of priorities that each port of the switch supports may be obtained from the port configuration message.
number, even across power cycles. The internal structure of the port number is opaque to the GSMP protocol. However, by looking up the product identity in a database, network management tools may discover the partitioning of the port number and the physical meaning of the sub-fields.
Each switch port also maintains a port session number assigned by the switch. A connection management message or a port management message with an incorrect port session number must be rejected. This allows the controller to detect a link failure and to keep state synchronized. The port session number of a port remains unchanged while the port is continuously in the available state and the link status is continuously up. When a port returns to the available state after it has been unavailable or in any of the loopback states, or when the line status returns to the up state after it has been down or in test, or after a power cycle, its port session number will have changed. Port session numbers should be assigned using some form of random number.
GSMP also contains an adjacency protocol. The adjacency protocol is used to synchronize state across the link, to discover the identity of the entity at the other end of a link, and to detect when it changes.
The LLC/SNAP header contains the octets: 0xAA 0xAA 0x03 0x00 0x00 0x00 0x88 0x0C.
The maximum transmission unit (MTU) of the GSMP message is 1500 octets.
synchronization across the link and maintain a handshake.
For the request-response messages each message type has a format for the request message and a format for the success response. Unless otherwise specified a failure response message is identical to the request message that caused the failure, with the Code field indicating the nature of the failure. Event messages have only a single format defined as they are not acknowledged by the controller.
synchronization, and all GSMP messages received on a link that does not currently have state synchronization must be discarded.
The GSMP protocol version number, currently Version = 1. It should be set by the sender of the message to the GSMP protocol version that the sender is currently running.
The GSMP message type. GSMP messages fall into five classes: Connection Management, Port Management, Statistics, Configuration, and Events. Each class, except for port management, has a number of different message types. In addition, one Message Type is allocated to the adjacency protocol.
Field in a connection management request message or a port management request message, is used to indicate whether a response is required to the request message if the outcome is successful. A value of "NoSuccessAck" indicates that the request message does not expect a response if the outcome is successful, and a value of "AckAll" indicates that a response is expected if the outcome is successful. In both cases a failure response will be generated if the request fails. This facility reduces the traffic in the case where the controller is simply checking that the state in the switch is correct. For all other request messages a value of "NoSuccessAck" in the request message is ignored and the request message is handled as if the field were set to "AckAll". In a response message the result field can have two values: "Success" and "Failure".
The Result field is not used in an adjacency protocol message and should be set to zero by the sender and ignored by the receiver.
Field gives further information concerning the result in a response message. It is mostly used to pass an error code in a failure response but can also be used to give further information in a success response message or an event message. In a request message the code field is not used and is set to zero. In an adjacency protocol message the Code field is used to determine the function of the message.
Used to associate a request message with its response message. For request messages the controller may select any transaction identifier. For response messages the transaction identifier is set to the value of the transaction identifier from the message to which it is a response. For event messages the transaction identifier should be set to zero. In the adjacency protocol the Transaction Identifier is not used. This field is not present in the adjacency protocol message.
Field gives the session number of the input port. Each switch port maintains a Port Session Number assigned by the switch. The port session number of a port remains unchanged while the port is continuously in the Available state and the link status is continuously Up. When a port returns to the Available state after it has been Unavailable or in any of the Loopback states, or when the line status returns to the Up state after it has been Down or in Test, or after a power cycle, a new Port Session Number must be generated. Port session numbers should be assigned using some form of random number. The switch must reject any connection management request message that has an invalid Port Session Number for the port specified in the Input Port field by returning a failure response message with the Code field indicating, "Invalid port session number." The current port session number may be obtained using a configuration message.
Indicates a switch input port. Switch ports are referenced by a 32 bit value assigned by the switch.
Identifies an ATM virtual path arriving at the switch input port indicated by the Input Port field.
Identifies an ATM virtual channel arriving on the virtual path indicated by the Input VPI field at the switch input port indicated by the Input Port field.
Indicates a switch output port. Switch ports are referenced by a 32 bit value assigned by the switch.
Identifies an outgoing virtual path departing from the switch output port indicated in the Output Port field.
Identifies an outgoing virtual channel departing on the virtual path indicated by the Output VPI field from the switch output port indicated in the Output Port field.
Gives the number of output branches on a virtual channel connection. (A unicast connection will have one branch, a multicast connection will have two or more branches.) This field is only used in the Verify Tree message. In all other connection management messages this field should be set to zero by the sender and ignored by the receiver.
This field is not used. It is set to zero by the sender and ignored by the receiver.
Move Branch messages. In all other connection management messages this field should be set to zero by the sender and ignored by the receiver.
If the result field of the request message is "AckAll" the switch must reply to all connection management request messages with a success response message or a failure response message. If the result field of the request message is "NoSuccessAck" the switch must only reply in the case of a failure.
A success response message must not be sent until the operation has been successfully completed. For connection management messages the success response message is a copy of the request message returned with a Result field indicating success. The Code field is not used in a connection management success response message and should be set to zero. The failure response message is a copy of the request message returned with a Result field indicating failure. The Code field is used to pass the Failure Code in a connection management failure response message. If the switch issues a failure response the connection state within the switch must not be modified by the request message that resulted in the failure.
No distinction is made between unicast connections and multicast connections. The first Add Branch message for a particular Input Port, Input VPI, and Input VCI will establish a unicast connection. The second Add Branch message with the same Input Port, Input VPI, and Input VCI fields will convert the connection to a multicast connection with two branches. Subsequent Add Branch messages with the same Input Port, Input VPI, and Input VCI fields will add further branches to the multicast connection. Use of the Delete Branch message on a multicast connection with two branches will result in a unicast connection. Use of the Delete Branch message on a unicast connection will delete the unicast connection. There is no concept of a connection with zero output branches. All connections are unidirectional, one input virtual channel to one or more output virtual channels.
The connection management messages may be issued regardless of the Port Status of the switch port. Connections may be established or deleted when a switch port is in the Available, Unavailable, or any of the Loopback states. However, all connection state on an input port will be deleted when the port returns to the Available state from any other state, i.e. when a Port Management message is received for that port with the Function field indicating either Bring Up, or Reset Input Port.
If the virtual channel connection specified by the Input Port, Input VPI, and Input VCI fields does not already exist, it must be established with the single output branch specified in the request message. The output branch should have the priority specified by the Priority field. If the Result field of the request message is "AckAll" a success response message must be sent upon successful establishment of the specified branch. The success response message must not be sent until the Add Branch operation has been completed.
If the virtual channel connection specified by the Input Port, Input VPI, and Input VCI fields already exists, but the specified output branch does not, the new output branch must be added. The new output branch should have the priority specified by the Priority field. If the Result field of the request message is "AckAll" a success response message must be sent upon successful establishment of the specified branch. The success response message must not be sent until the Add Branch operation has been completed.
If the virtual channel connection specified by the Input Port, Input VPI, and Input VCI fields already exists and the specified output branch also already exists, the priority of the connection, if different from the request message, should be changed to that in the request message. A success response message must be sent if the Result field of the request message is "AckAll". This allows the controller to periodically reassert the state of a connection or to change its priority. If the result field of the request message is "NoSuccessAck" a success response message should not be returned. This may be used to reduce the traffic on the control link for messages that are reasserting previously established state. For messages that are reasserting previously established state, the switch must always check that this state is correctly established in the switch hardware (i.e. the actual connection tables used to forward cells).
The behavior is undefined if the output virtual channel specified by the Output Port, Output VPI, and Output VCI fields is already in use by any connection other than that specified by the Input Port, Input VPI, and Input VCI fields.
A failure response must be returned if the switch is unable to establish the specified branch or if there is an error in any of the fields of the request message. If a failure message is returned the state of the switch must not have been modified by the request message.
It should be noted that different switches support multicast in different ways. There will be a limit to the total number of multicast connections any switch can support, and possibly a limit on the maximum number of branches that a multicast connection may specify. Some switches also impose a limit on the number of different VPI/VCI values that may be assigned to the output branches of a multicast connection. Many switches are incapable of supporting more than a single branch of any particular multicast connection on the same output port. Specific failure codes are defined for some of these conditions. If a switch sends a failure response to an Add Branch message it must choose the most specific failure code.
If the Result field of the request message is "AckAll" a success response message must be sent upon successful deletion of the specified branch. The success response message must not be sent until the delete branch operation has been completed and if possible, not until all data on that branch, queued for transmission, has been transmitted. A failure message indicating, "The specified connection does not exist," must be sent if the connection specified by the Input Port, Input VPI, and Input VCI fields does not exist. A failure message indicating, "The specified branch does not exist," must be sent if the connection specified by the Input Port, Input VPI, and Input VCI fields exists but the branch specified by the Output Port, Output VPI, and Output VCI fields does not exist.
If the Result field of the request message is "AckAll" a success response message must be sent upon successful deletion of the specified connection. The success message must not be sent until the delete operation has been completed and if possible, not until all data on the connection, queued for transmission, has been transmitted. A failure message indicating, "The specified connection does not exist," must be sent if the connection specified by the Input Port, Input VPI, and Input VCI fields does not exist.
"The specified connection does not exist." In this case the Number of Branches field will be the same as that of the request message.
The Verify Tree message can only be guaranteed to yield a correct response when there are no other connection request messages or their response messages pending for the specified connection. If this is not the case the result of the Verify Tree message is undefined.
The Delete All message is a connection management message used to delete all connections on a switch input port. All connections that arrive at the specified input port must be deleted. On completion of the operation all dynamically assigned VPI/VCI values for the specified port must be unassigned, i.e. there must be no virtual connections established in the VPI/VCI space that GSMP controls on this port. The Input VPI, Input VCI, Output Port, Output VPI, and Output VCI fields are not used in this message and their contents are ignored and unspecified. The Delete All message is"
If the Result field of the request message is "AckAll" a success response message must be sent upon completion of the operation. The success response message must not be sent until the operation has been completed.
If the virtual channel connection specified by the Input Port, Input VPI, and Input VCI fields already exists, and the output branch specified by the Old Output Port, Old Output VPI, and Old Output VCI fields exists as a branch on that connection, the output branch specified by the New Output Port, New Output VPI, and New Output VCI fields is added to the connection and the branch specified by the Old Output Port, Old Output VPI, and Old Output VCI fields is deleted. If the Result field of the request message is "AckAll" a success response message must be sent upon successful completion of the operation. The success response message must not be sent until the Move Branch operation has been completed.
If the virtual channel connection specified by the Input Port, Input VPI, and Input VCI fields already exists, but the output branch specified by the Old Output Port, Old Output VPI, and Old Output VCI fields does not exist as a branch on that connection, a failure response must be returned with the Code field indicating, "The specified branch does not exist." The connection state of the switch must not be modified in this case.
If the virtual channel connection specified by the Input Port, Input VPI, and Input VCI fields does not exist, a failure response must be returned with the Code field indicating, "The specified connection does not exist." The connection state of the switch must not be modified in this case.
The behavior is undefined if the output virtual channel specified by the New Output Port, New Output VPI, and New Output VCI fields is already in use by any connection.
A failure response will be returned if the switch is unable to establish the specified branch or if there is an error in any of the fields of the request message. If a failure message is returned the state of the switch must not have been modified by the request message.
Gives the port number of the port to which the message applies.
Gives the current port session number for the port. If the Port Session Number in the request message does not match the current port session number of the port indicated by the Port field of the request message, a failure response must be returned with, "Invalid port session number," indicated in the Code field. If the specified function requires a new Port Session Number to be generated the new Port Session Number must be given in the success response message. The Port Session Number must be generated using some form of random number.
In the success response message gives the current value of the Event Sequence Number of the switch port indicated by the Port field. The Event Sequence Number is set to zero when the port is initialized and is incremented by one each time an asynchronous event is detected on that port that the switch would normally report via an Event message. If the Event Sequence Number in the success response differs from the Event Sequence Number of the most recent Event message received for that port, events have occurred that were not reported via an Event message. This is most likely to be due to the flow control that restricts the rate at which a switch can send Event messages for each port. In the request message this field is not used and should be set to zero by the sender and ignored by the receiver.
Field in the request message is used to reset the Event Flags in the switch port indicated by the Port field. Each Event Flag in a switch port corresponds to a type of Event message. When a switch port sends an Event message it sets the corresponding Event Flag on that port. The port is not permitted to send another Event message of the same type until the Event Flag has been reset. If the Function field in the request message is set to "Reset Event Flags," for each bit that is set in the Event Flags field, the corresponding Event Flag in the switch port is reset.
The Event Flags field is only used in a request message with the Function field set to "Reset Event Flags." For all other values of the Function field, the Event Flags field should be set to zero in the request message and must be ignored by the receiver. In the success response message the Event Flags field must be set to the current value of the Event Flags for the port, after the completion of the operation specified by the request message, for all values of the Function field. Setting the Event Flags field to all zeros in a "Reset Event Flags" request message allows the controller to obtain the current state of the Event Flags and the current Event Sequence Number of the port without changing the state of the Event Flags.
Is the length of time, in seconds, that any of the loopback states remain in operation. When the duration has expired the port will automatically be returned to service. If another Port Management message is received for the same port before the duration has expired, the loopback will continue to remain in operation for the length of time specified by the Duration field in the new message. The Duration field is only used in request messages with the Function field set to Internal Loopback, External Loopback, or Bothway Loopback. In all other request messages it should be set to zero by the sender and ignored by the receiver.
Function = 1. Bring the port into service. All connections that arrive at the specified input port must be deleted and a new Port Session Number must be selected using some form of random number. On completion of the operation all dynamically assigned VPI/VCI values for the specified input port must be unassigned, i.e. no virtual connections will be established in the VPI/VCI space that GSMP controls on this input port. The Port Status of the port afterwards will be Available.
Function = 2. Take the port out of service. Any cells received at this port will be discarded. No cells will be transmitted from this port. The Port Status of the port afterwards will be Unavailable. The behavior is undefined if the port over which the GSMP protocol is running is taken down.
Function = 3. Cells arriving at the output port from the switch fabric are looped through to the input port to return to the switch fabric. All of the ATM functions of the input port above the PHY layer, e.g. header translation, are performed upon the looped back cells. The Port Status of the port afterwards will be Internal Loopback.
Function = 4. Cells arriving at the input port from the external communications link are immediately looped back to the communications link at the physical layer without entering the input port. None of the ATM functions of the input port above the PHY layer are performed upon the looped back cells. The Port Status of the port afterwards will be External Loopback.
Function = 5. Both internal and external loopback are performed. The Port Status of the port afterwards will be Bothway Loopback.
Function = 6. All connections that arrive at the specified input port must be deleted and the input and output port hardware re-initialized. On completion of the operation all dynamically assigned VPI/VCI values for the specified input port must be unassigned, i.e. no virtual connections will be established in the VPI/VCI space that GSMP controls on this input port. The Port Session Number is not changed by the Reset Input Port function. The Port Status of the port afterwards will be Unavailable.
Function = 7. For each bit that is set in the Event Flags field, the corresponding Event Flag in the switch port must be reset. The Port Status of the port is not changed by this function.
The statistics messages permit the controller to request the values of various hardware counters associated with the switch input and output ports, and virtual channels. Two classes of statistics message are defined: the VC Activity Message, and the Port and VC Statistics Messages. The VC Activity message is used to determine whether one or more specific VCs have recently been carrying traffic. The Port and VC Statistics message is used to query the various port and VC specific traffic and error counters.
Field specifies the number of VC Activity records to follow. The maximum number of VC Activity records permitted in a single VC Activity message is 120.
Field is not used. It is set to zero by the sender and ignored by the receiver.
Identifies the port number of the input port on which the VC of interest arrives in order to identify the VC (regardless of whether the traffic count for the VC is maintained on the input port or the output port).
Fields identify the specific virtual channel for which statistics are being requested.
Bit 1 of the Flags field: if set, indicates that the value in bit 2 of the Flags field is valid; if zero, indicates that the value in the VC Traffic Count field is valid.
If bit 1 of the Flags field is set, bit 2 of the Flags field, if set, indicates that there has been some activity on this virtual channel since the last VC Activity message for this virtual channel.
If bit 1 of the Flags field is set, bit 2 of the Flags field, if zero, indicates that there has been no activity on this virtual channel since the last VC Activity message for this virtual channel.
Bit 3 of the Flags field is not used, it should be set to zero by the sender and ignored by the receiver.
using the traffic count rather than using bit 2 of the Flags field.
The format of the failure response is the same as the request message with the Number of Records field set to zero and no VC Activity records returned in the message. If the switch is incapable of detecting per-VC activity, a failure response must be returned indicating, "The specified request is not implemented on this switch."
The Port and VC Statistics messages are used to query the various port and VC specific traffic and error counters.
Identifies the port number of the port for which statistics are being requested.
Fields identify the specific virtual channel for which statistics are being requested. For requests that do not require a virtual channel to be specified these fields should be set to zero in the request and ignored by the receiver.
Fields are the same as those of the request message.
Each gives the value of a free running 64 bit counter counting cells arriving at the input or departing from the output respectively. In response to a Port Statistics message the count will be on a per port basis and in response to a VC Statistics message the count will be on a per VC basis.
Each gives the value of a free running 64 bit counter counting frames (packets) arriving at the input or departing from the output respectively. In response to a Port Statistics message the count will be on a per port basis and in response to a VC Statistics message the count will be on a per VC basis.
Each gives the value of a free running 64 bit counter counting cells discarded due to queue overflow on an input port or on an output port respectively. In response to a Port Statistics message the count will be on a per port basis and in response to a VC Statistics message the count will be on a per VC basis.
Each gives the value of a free running 64 bit counter counting frames discarded due to queue overflow on an input port or on an output port respectively. In response to a Port Statistics message the count will be on a per port basis and in response to a VC Statistics message the count will be on a per VC basis.
Gives the value of a free running 64 bit counter counting cells discarded due to header checksum errors on arrival at an input port.
Gives the value of a free running 64 bit counter counting cells discarded because their VPI/VCI is invalid on arrival at an input port. An incoming VPI/VCI is invalid if no connection is currently established having that value of VPI/VCI.
The configuration messages permit the controller to discover the capabilities of the switch. Three configuration request messages have been defined: Switch, Port, and All Ports.
Identifies the port number for which configuration information is being requested. If the Port field is not required by the message it is set to zero by the sender and ignored by the receiver.
The Port field is not used in the request message and is set to zero.
The version number of the switch control firmware installed.
A 16 bit field allocated by the manufacturer of the switch. (For these purposes the manufacturer of the switch is assumed to be the organization identified by the OUI in the Switch Name field.) The Switch Type identifies the product. When the Switch Type is combined with the OUI from the Switch Name the product is uniquely identified. Network Management may use this identification to obtain product related information from a database.
A 48 bit quantity that is unique within the operational context of the device. A 48 bit IEEE 802 MAC address, if available, may be used as the Switch Name. The most significant 24 bits of the Switch Name must be an Organizationally Unique Identifier (OUI) that identifies the manufacturer of the switch.
The switch port to which the configuration information refers. Configuration information relating to both the input and the output sides of the switch port is given. Port numbers are 32 bits wide and allocated by the switch. The switch may choose to structure the 32 bits into sub fields that have meaning to the physical structure of the switch hardware (e.g. shelf, slot, interface).
The current Port Session Number for the specified port. Each switch port maintains a Port Session Number assigned by the switch. The Port Session Number of a port remains unchanged while the port is continuously in the Available state. When a port returns to the Available state after it has been Unavailable, or after a power cycle, its Port Session Number must be changed, preferably using some form of random number.
The minimum value of dynamically assigned incoming VPI that the connection table on the input port can support and may be controlled by GSMP.
can handle all values of VPI within the range Min VPI to Max VPI inclusive and that GSMP may control all values within this range. If the switch does not support virtual paths it is acceptable for both Min VPI and Max VPI to specify the same value, most likely zero.
The minimum value of dynamically assigned incoming VCI that the connection table on the input port can support and may be controlled by GSMP.
The maximum value of dynamically assigned incoming VCI that the connection table on the input port can support and may be controlled by GSMP. It is assumed that the input port can handle all values of VCI within the range Min VCI to Max VCI inclusive for each of the virtual paths in the range Min VPI to Max VPI inclusive and that GSMP may control all values within this range.
A measure of the bandwidth of the port. It is the rate of cells arriving at or departing from the port in cells/s. It is assumed that both input port and output port have the same cell rate.
Port Status = 1. The port is available to both send and receive cells. When a port changes to the Available state from any other administrative state, all dynamically assigned virtual connections must be cleared and a new Port Session Number must be generated.
Port Status = 2. The port has intentionally been taken out of service. No cells will be transmitted from this port. No cells will be received by this port.
switch fabric. All of the ATM functions of the input port above the PHY layer, e.g. header translation, are performed upon the looped back cells.
Port Status = 4. The port has intentionally been taken out of service and is in external loopback: cells arriving at the input port from the external communications link are immediately looped back to the communications link at the physical layer without entering the input port. None of the ATM functions of the input port above the PHY layer are performed upon the looped back cells.
Port Status = 5. The port has intentionally been taken out of service and is in both internal and external loopback.
The type of physical transmission interface for this port. The values for this field are given by the IANAifTYPE object from the MIB defined for the IANAifTYPE-MIB specified in RFC 1573 [rfc1573]. Example values are: SONET or SDH (39), DS-3 (30).
Line Status = 1. The line is able to both send and receive cells. When the Line Status changes to Up from either the Down or Test states, a new Port Session Number must be generated.
Line Status = 2. The line is unable either to send or receive cells or both.
Line Status = 3. The port or line is in a test mode, for example, power-on test.
The number of different priorities that this output port can assign to virtual channel connections. Zero is invalid in this field. If an output port is able to support "Q"
priorities, the highest priority is numbered zero and the lowest priority is numbered "Q-1". The ability to offer different qualities of service to different connections based upon their priority is assumed to be a property of the output port of the switch. It may be assumed that for virtual channel connections that share the same output port, an ATM cell on a connection with a higher priority is much more likely to exit the switch before an ATM cell on a connection with a lower priority if they are both in the switch at the same time.
Field gives the number of Port Records to follow in the message. The maximum number of port records allowed in a single All Ports Configuration success response is 64. If a switch has more than 64 ports it must send them in multiple success response messages.
the future definition of further fields at the end of the port record while preserving compatibility with earlier versions of the protocol.
The definition of the fields in the port record is exactly the same as that of the Port Configuration message.
Field gives the switch port to which the event message refers.
The current Port Session Number for the specified port.
The current value of the Event Sequence Number for the specified port. The Event Sequence Number is set to zero when the port is initialized and is incremented by one each time an asynchronous event is detected on that port that the switch would normally report via an Event message. The Event Sequence Number must be incremented each time an event occurs even if the switch is prevented from sending an Event message due to the action of the flow control.
Field gives the VPI/VCI to which the event message refers. If this field is not required by the event message it is set to zero.
prevented from reporting the event due to the action of the flow control. This allows the controller to detect that it has not been informed of some events that have occurred on the port due to the action of the flow control.
The adjacency protocol is used to synchronize state across the link, to discover the identity of the entity at the other end of a link, and to detect when it changes. No GSMP messages other than those of the adjacency protocol may be sent across the link until the adjacency protocol has achieved synchronization.
Field is not used in the adjacency protocol. It should be set to zero by the sender and ignored by the receiver.
For the SYN, SYNACK, and ACK messages, is the name of the entity sending the message. The Sender Name is a 48 bit quantity that is unique within the operational context of the device. A 48 bit IEEE 802 MAC address, if available, may be used for the Sender Name. For the RSTACK message, the Sender Name field is set to the value of the Receiver Name field from the incoming message that caused the RSTACK message to be generated.
For the SYN, SYNACK, and ACK messages, is the name of the entity that the sender of the message believes is at the far end of the link. If the sender of the message does not know the name of the entity at the far end of the link, this field should be set to zero. For the RSTACK message, the Receiver Name field is set to the value of the Sender Name field from the incoming message that caused the RSTACK message to be generated.
For the SYN, SYNACK, and ACK messages, is the local port number of the link across which the message is being sent. Port numbers are locally assigned 32 bit values. For the RSTACK message, the Sender Port field is set to the value of the Receiver Port field from the incoming message that caused the RSTACK message to be generated.
For the SYN, SYNACK, and ACK messages, is what the sender believes is the local port number for the link, allocated by the entity at the far end of the link. If the sender of the message does not know the port number at the far end of the link, this field should be set to zero. For the RSTACK message, the Receiver Port field is set to the value of the Sender Port field from the incoming message that caused the RSTACK message to be generated.
For the SYN, SYNACK, and ACK messages, is the sender's instance number for the link. It is used to detect when the link comes back up after going down or when the identity of the entity at the other end of the link changes. The instance number is a 32 bit number that is guaranteed to be unique within the recent past and to change when the link or node comes back up after going down. Zero is not a valid instance number. For the RSTACK message, the Sender Instance field is set to the value of the Receiver Instance field from the incoming message that caused the RSTACK message to be generated.
field is set to the value of the Sender Instance field from the incoming message that caused the RSTACK message to be generated.
The adjacency protocol is described by the rules and state tables given in this section.
The "Update Peer Verifier" operation is defined as storing the values of the Sender Instance, Sender Port, and Sender Name fields from a SYN or SYNACK message received from the entity at the far end of the link.
previous message by the "Update Peer Verifier" operation.
sent in outgoing SYN, SYNACK, and ACK messages.
"!" Represents the logical negation (NOT) operation.
A timer is required for the periodic generation of SYN, SYNACK, and ACK messages. The period of the timer is unspecified but a value of one second is suggested.
Else the following State Tables.
State synchronization across a link is considered to be achieved when the protocol reaches the ESTAB state.
Note 1: No more than one ACK should be sent within any time period of length defined by the timer.
1: Unspecified reason not covered by other failure codes. 2: Invalid request message.
3: The specified request is not implemented on this switch. 4: Invalid port session number.
5: One or more of the specified ports does not exist.
6: One or more of the specified ports is down.
7: One or more of the specified VPIs or VCIs is out of range on one or more of the requested ports.
8: The specified connection does not exist.
9: The specified branch does not exist.
10: A branch belonging to the specified multicast connection is already established on the specified output port and the switch cannot support more than a single branch of any multicast connection on the same output port.
11: The limit on the maximum number of multicast connections that the switch can support has been reached.
12: The limit on the maximum number of branches that the specified multicast connection can support has been reached. 13: Unable to assign the requested VPI/VCI value to the requested branch on the specified multicast connection.
14: General problem related to the manner in which multicast is supported by the switch.
15: Out of resources (e.g. memory exhausted, etc.).
16: Failure specific to the particular message type.
Telecommunication Union, ITU-T Recommendation I.361, Mar.
[I.363]   "B-ISDN ATM Adaptation Layer (AAL) Specification,"
[rfc1700] "Assigned Numbers," STD 2, RFC 1700, October 1994.
[rfc1573] "Evolution of the Interfaces Group of MIB-II," RFC 1573, January 1994.