1package apimanagement
2
3// Copyright (c) Microsoft and contributors.  All rights reserved.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13//
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
17// Code generated by Microsoft (R) AutoRest Code Generator.
18// Changes may cause incorrect behavior and will be lost if the code is regenerated.
19
20import (
21	"context"
22	"github.com/Azure/go-autorest/autorest"
23	"github.com/Azure/go-autorest/autorest/azure"
24	"github.com/Azure/go-autorest/autorest/validation"
25	"github.com/Azure/go-autorest/tracing"
26	"net/http"
27)
28
29// ProductAPIClient is the apiManagement Client
30type ProductAPIClient struct {
31	BaseClient
32}
33
34// NewProductAPIClient creates an instance of the ProductAPIClient client.
35func NewProductAPIClient(subscriptionID string) ProductAPIClient {
36	return NewProductAPIClientWithBaseURI(DefaultBaseURI, subscriptionID)
37}
38
39// NewProductAPIClientWithBaseURI creates an instance of the ProductAPIClient client.
40func NewProductAPIClientWithBaseURI(baseURI string, subscriptionID string) ProductAPIClient {
41	return ProductAPIClient{NewWithBaseURI(baseURI, subscriptionID)}
42}
43
44// CheckEntityExists checks that API entity specified by identifier is associated with the Product entity.
45// Parameters:
46// resourceGroupName - the name of the resource group.
47// serviceName - the name of the API Management service.
48// productID - product identifier. Must be unique in the current API Management service instance.
49// apiid - API revision identifier. Must be unique in the current API Management service instance. Non-current
50// revision has ;rev=n as a suffix where n is the revision number.
51func (client ProductAPIClient) CheckEntityExists(ctx context.Context, resourceGroupName string, serviceName string, productID string, apiid string) (result autorest.Response, err error) {
52	if tracing.IsEnabled() {
53		ctx = tracing.StartSpan(ctx, fqdn+"/ProductAPIClient.CheckEntityExists")
54		defer func() {
55			sc := -1
56			if result.Response != nil {
57				sc = result.Response.StatusCode
58			}
59			tracing.EndSpan(ctx, sc, err)
60		}()
61	}
62	if err := validation.Validate([]validation.Validation{
63		{TargetValue: serviceName,
64			Constraints: []validation.Constraint{{Target: "serviceName", Name: validation.MaxLength, Rule: 50, Chain: nil},
65				{Target: "serviceName", Name: validation.MinLength, Rule: 1, Chain: nil},
66				{Target: "serviceName", Name: validation.Pattern, Rule: `^[a-zA-Z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$`, Chain: nil}}},
67		{TargetValue: productID,
68			Constraints: []validation.Constraint{{Target: "productID", Name: validation.MaxLength, Rule: 256, Chain: nil},
69				{Target: "productID", Name: validation.MinLength, Rule: 1, Chain: nil}}},
70		{TargetValue: apiid,
71			Constraints: []validation.Constraint{{Target: "apiid", Name: validation.MaxLength, Rule: 256, Chain: nil},
72				{Target: "apiid", Name: validation.MinLength, Rule: 1, Chain: nil},
73				{Target: "apiid", Name: validation.Pattern, Rule: `^[^*#&+:<>?]+$`, Chain: nil}}}}); err != nil {
74		return result, validation.NewError("apimanagement.ProductAPIClient", "CheckEntityExists", err.Error())
75	}
76
77	req, err := client.CheckEntityExistsPreparer(ctx, resourceGroupName, serviceName, productID, apiid)
78	if err != nil {
79		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "CheckEntityExists", nil, "Failure preparing request")
80		return
81	}
82
83	resp, err := client.CheckEntityExistsSender(req)
84	if err != nil {
85		result.Response = resp
86		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "CheckEntityExists", resp, "Failure sending request")
87		return
88	}
89
90	result, err = client.CheckEntityExistsResponder(resp)
91	if err != nil {
92		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "CheckEntityExists", resp, "Failure responding to request")
93	}
94
95	return
96}
97
98// CheckEntityExistsPreparer prepares the CheckEntityExists request.
99func (client ProductAPIClient) CheckEntityExistsPreparer(ctx context.Context, resourceGroupName string, serviceName string, productID string, apiid string) (*http.Request, error) {
100	pathParameters := map[string]interface{}{
101		"apiId":             autorest.Encode("path", apiid),
102		"productId":         autorest.Encode("path", productID),
103		"resourceGroupName": autorest.Encode("path", resourceGroupName),
104		"serviceName":       autorest.Encode("path", serviceName),
105		"subscriptionId":    autorest.Encode("path", client.SubscriptionID),
106	}
107
108	const APIVersion = "2019-01-01"
109	queryParameters := map[string]interface{}{
110		"api-version": APIVersion,
111	}
112
113	preparer := autorest.CreatePreparer(
114		autorest.AsHead(),
115		autorest.WithBaseURL(client.BaseURI),
116		autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ApiManagement/service/{serviceName}/products/{productId}/apis/{apiId}", pathParameters),
117		autorest.WithQueryParameters(queryParameters))
118	return preparer.Prepare((&http.Request{}).WithContext(ctx))
119}
120
121// CheckEntityExistsSender sends the CheckEntityExists request. The method will close the
122// http.Response Body if it receives an error.
123func (client ProductAPIClient) CheckEntityExistsSender(req *http.Request) (*http.Response, error) {
124	sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client))
125	return autorest.SendWithSender(client, req, sd...)
126}
127
128// CheckEntityExistsResponder handles the response to the CheckEntityExists request. The method always
129// closes the http.Response Body.
130func (client ProductAPIClient) CheckEntityExistsResponder(resp *http.Response) (result autorest.Response, err error) {
131	err = autorest.Respond(
132		resp,
133		client.ByInspecting(),
134		azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusNoContent),
135		autorest.ByClosing())
136	result.Response = resp
137	return
138}
139
140// CreateOrUpdate adds an API to the specified product.
141// Parameters:
142// resourceGroupName - the name of the resource group.
143// serviceName - the name of the API Management service.
144// productID - product identifier. Must be unique in the current API Management service instance.
145// apiid - API revision identifier. Must be unique in the current API Management service instance. Non-current
146// revision has ;rev=n as a suffix where n is the revision number.
147func (client ProductAPIClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, serviceName string, productID string, apiid string) (result APIContract, err error) {
148	if tracing.IsEnabled() {
149		ctx = tracing.StartSpan(ctx, fqdn+"/ProductAPIClient.CreateOrUpdate")
150		defer func() {
151			sc := -1
152			if result.Response.Response != nil {
153				sc = result.Response.Response.StatusCode
154			}
155			tracing.EndSpan(ctx, sc, err)
156		}()
157	}
158	if err := validation.Validate([]validation.Validation{
159		{TargetValue: serviceName,
160			Constraints: []validation.Constraint{{Target: "serviceName", Name: validation.MaxLength, Rule: 50, Chain: nil},
161				{Target: "serviceName", Name: validation.MinLength, Rule: 1, Chain: nil},
162				{Target: "serviceName", Name: validation.Pattern, Rule: `^[a-zA-Z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$`, Chain: nil}}},
163		{TargetValue: productID,
164			Constraints: []validation.Constraint{{Target: "productID", Name: validation.MaxLength, Rule: 256, Chain: nil},
165				{Target: "productID", Name: validation.MinLength, Rule: 1, Chain: nil}}},
166		{TargetValue: apiid,
167			Constraints: []validation.Constraint{{Target: "apiid", Name: validation.MaxLength, Rule: 256, Chain: nil},
168				{Target: "apiid", Name: validation.MinLength, Rule: 1, Chain: nil},
169				{Target: "apiid", Name: validation.Pattern, Rule: `^[^*#&+:<>?]+$`, Chain: nil}}}}); err != nil {
170		return result, validation.NewError("apimanagement.ProductAPIClient", "CreateOrUpdate", err.Error())
171	}
172
173	req, err := client.CreateOrUpdatePreparer(ctx, resourceGroupName, serviceName, productID, apiid)
174	if err != nil {
175		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "CreateOrUpdate", nil, "Failure preparing request")
176		return
177	}
178
179	resp, err := client.CreateOrUpdateSender(req)
180	if err != nil {
181		result.Response = autorest.Response{Response: resp}
182		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "CreateOrUpdate", resp, "Failure sending request")
183		return
184	}
185
186	result, err = client.CreateOrUpdateResponder(resp)
187	if err != nil {
188		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "CreateOrUpdate", resp, "Failure responding to request")
189	}
190
191	return
192}
193
194// CreateOrUpdatePreparer prepares the CreateOrUpdate request.
195func (client ProductAPIClient) CreateOrUpdatePreparer(ctx context.Context, resourceGroupName string, serviceName string, productID string, apiid string) (*http.Request, error) {
196	pathParameters := map[string]interface{}{
197		"apiId":             autorest.Encode("path", apiid),
198		"productId":         autorest.Encode("path", productID),
199		"resourceGroupName": autorest.Encode("path", resourceGroupName),
200		"serviceName":       autorest.Encode("path", serviceName),
201		"subscriptionId":    autorest.Encode("path", client.SubscriptionID),
202	}
203
204	const APIVersion = "2019-01-01"
205	queryParameters := map[string]interface{}{
206		"api-version": APIVersion,
207	}
208
209	preparer := autorest.CreatePreparer(
210		autorest.AsPut(),
211		autorest.WithBaseURL(client.BaseURI),
212		autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ApiManagement/service/{serviceName}/products/{productId}/apis/{apiId}", pathParameters),
213		autorest.WithQueryParameters(queryParameters))
214	return preparer.Prepare((&http.Request{}).WithContext(ctx))
215}
216
217// CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the
218// http.Response Body if it receives an error.
219func (client ProductAPIClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) {
220	sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client))
221	return autorest.SendWithSender(client, req, sd...)
222}
223
224// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always
225// closes the http.Response Body.
226func (client ProductAPIClient) CreateOrUpdateResponder(resp *http.Response) (result APIContract, err error) {
227	err = autorest.Respond(
228		resp,
229		client.ByInspecting(),
230		azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
231		autorest.ByUnmarshallingJSON(&result),
232		autorest.ByClosing())
233	result.Response = autorest.Response{Response: resp}
234	return
235}
236
237// Delete deletes the specified API from the specified product.
238// Parameters:
239// resourceGroupName - the name of the resource group.
240// serviceName - the name of the API Management service.
241// productID - product identifier. Must be unique in the current API Management service instance.
242// apiid - API revision identifier. Must be unique in the current API Management service instance. Non-current
243// revision has ;rev=n as a suffix where n is the revision number.
244func (client ProductAPIClient) Delete(ctx context.Context, resourceGroupName string, serviceName string, productID string, apiid string) (result autorest.Response, err error) {
245	if tracing.IsEnabled() {
246		ctx = tracing.StartSpan(ctx, fqdn+"/ProductAPIClient.Delete")
247		defer func() {
248			sc := -1
249			if result.Response != nil {
250				sc = result.Response.StatusCode
251			}
252			tracing.EndSpan(ctx, sc, err)
253		}()
254	}
255	if err := validation.Validate([]validation.Validation{
256		{TargetValue: serviceName,
257			Constraints: []validation.Constraint{{Target: "serviceName", Name: validation.MaxLength, Rule: 50, Chain: nil},
258				{Target: "serviceName", Name: validation.MinLength, Rule: 1, Chain: nil},
259				{Target: "serviceName", Name: validation.Pattern, Rule: `^[a-zA-Z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$`, Chain: nil}}},
260		{TargetValue: productID,
261			Constraints: []validation.Constraint{{Target: "productID", Name: validation.MaxLength, Rule: 256, Chain: nil},
262				{Target: "productID", Name: validation.MinLength, Rule: 1, Chain: nil}}},
263		{TargetValue: apiid,
264			Constraints: []validation.Constraint{{Target: "apiid", Name: validation.MaxLength, Rule: 256, Chain: nil},
265				{Target: "apiid", Name: validation.MinLength, Rule: 1, Chain: nil},
266				{Target: "apiid", Name: validation.Pattern, Rule: `^[^*#&+:<>?]+$`, Chain: nil}}}}); err != nil {
267		return result, validation.NewError("apimanagement.ProductAPIClient", "Delete", err.Error())
268	}
269
270	req, err := client.DeletePreparer(ctx, resourceGroupName, serviceName, productID, apiid)
271	if err != nil {
272		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "Delete", nil, "Failure preparing request")
273		return
274	}
275
276	resp, err := client.DeleteSender(req)
277	if err != nil {
278		result.Response = resp
279		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "Delete", resp, "Failure sending request")
280		return
281	}
282
283	result, err = client.DeleteResponder(resp)
284	if err != nil {
285		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "Delete", resp, "Failure responding to request")
286	}
287
288	return
289}
290
291// DeletePreparer prepares the Delete request.
292func (client ProductAPIClient) DeletePreparer(ctx context.Context, resourceGroupName string, serviceName string, productID string, apiid string) (*http.Request, error) {
293	pathParameters := map[string]interface{}{
294		"apiId":             autorest.Encode("path", apiid),
295		"productId":         autorest.Encode("path", productID),
296		"resourceGroupName": autorest.Encode("path", resourceGroupName),
297		"serviceName":       autorest.Encode("path", serviceName),
298		"subscriptionId":    autorest.Encode("path", client.SubscriptionID),
299	}
300
301	const APIVersion = "2019-01-01"
302	queryParameters := map[string]interface{}{
303		"api-version": APIVersion,
304	}
305
306	preparer := autorest.CreatePreparer(
307		autorest.AsDelete(),
308		autorest.WithBaseURL(client.BaseURI),
309		autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ApiManagement/service/{serviceName}/products/{productId}/apis/{apiId}", pathParameters),
310		autorest.WithQueryParameters(queryParameters))
311	return preparer.Prepare((&http.Request{}).WithContext(ctx))
312}
313
314// DeleteSender sends the Delete request. The method will close the
315// http.Response Body if it receives an error.
316func (client ProductAPIClient) DeleteSender(req *http.Request) (*http.Response, error) {
317	sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client))
318	return autorest.SendWithSender(client, req, sd...)
319}
320
321// DeleteResponder handles the response to the Delete request. The method always
322// closes the http.Response Body.
323func (client ProductAPIClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
324	err = autorest.Respond(
325		resp,
326		client.ByInspecting(),
327		azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusNoContent),
328		autorest.ByClosing())
329	result.Response = resp
330	return
331}
332
333// ListByProduct lists a collection of the APIs associated with a product.
334// Parameters:
335// resourceGroupName - the name of the resource group.
336// serviceName - the name of the API Management service.
337// productID - product identifier. Must be unique in the current API Management service instance.
338// filter - |   Field     |     Usage     |     Supported operators     |     Supported functions
339// |</br>|-------------|-------------|-------------|-------------|</br>| name | filter | ge, le, eq, ne, gt, lt
340// | substringof, contains, startswith, endswith | </br>| displayName | filter | ge, le, eq, ne, gt, lt |
341// substringof, contains, startswith, endswith | </br>| description | filter | ge, le, eq, ne, gt, lt |
342// substringof, contains, startswith, endswith | </br>| serviceUrl | filter | ge, le, eq, ne, gt, lt |
343// substringof, contains, startswith, endswith | </br>| path | filter | ge, le, eq, ne, gt, lt | substringof,
344// contains, startswith, endswith | </br>
345// top - number of records to return.
346// skip - number of records to skip.
347func (client ProductAPIClient) ListByProduct(ctx context.Context, resourceGroupName string, serviceName string, productID string, filter string, top *int32, skip *int32) (result APICollectionPage, err error) {
348	if tracing.IsEnabled() {
349		ctx = tracing.StartSpan(ctx, fqdn+"/ProductAPIClient.ListByProduct")
350		defer func() {
351			sc := -1
352			if result.ac.Response.Response != nil {
353				sc = result.ac.Response.Response.StatusCode
354			}
355			tracing.EndSpan(ctx, sc, err)
356		}()
357	}
358	if err := validation.Validate([]validation.Validation{
359		{TargetValue: serviceName,
360			Constraints: []validation.Constraint{{Target: "serviceName", Name: validation.MaxLength, Rule: 50, Chain: nil},
361				{Target: "serviceName", Name: validation.MinLength, Rule: 1, Chain: nil},
362				{Target: "serviceName", Name: validation.Pattern, Rule: `^[a-zA-Z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$`, Chain: nil}}},
363		{TargetValue: productID,
364			Constraints: []validation.Constraint{{Target: "productID", Name: validation.MaxLength, Rule: 256, Chain: nil},
365				{Target: "productID", Name: validation.MinLength, Rule: 1, Chain: nil}}},
366		{TargetValue: top,
367			Constraints: []validation.Constraint{{Target: "top", Name: validation.Null, Rule: false,
368				Chain: []validation.Constraint{{Target: "top", Name: validation.InclusiveMinimum, Rule: 1, Chain: nil}}}}},
369		{TargetValue: skip,
370			Constraints: []validation.Constraint{{Target: "skip", Name: validation.Null, Rule: false,
371				Chain: []validation.Constraint{{Target: "skip", Name: validation.InclusiveMinimum, Rule: 0, Chain: nil}}}}}}); err != nil {
372		return result, validation.NewError("apimanagement.ProductAPIClient", "ListByProduct", err.Error())
373	}
374
375	result.fn = client.listByProductNextResults
376	req, err := client.ListByProductPreparer(ctx, resourceGroupName, serviceName, productID, filter, top, skip)
377	if err != nil {
378		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "ListByProduct", nil, "Failure preparing request")
379		return
380	}
381
382	resp, err := client.ListByProductSender(req)
383	if err != nil {
384		result.ac.Response = autorest.Response{Response: resp}
385		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "ListByProduct", resp, "Failure sending request")
386		return
387	}
388
389	result.ac, err = client.ListByProductResponder(resp)
390	if err != nil {
391		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "ListByProduct", resp, "Failure responding to request")
392	}
393
394	return
395}
396
397// ListByProductPreparer prepares the ListByProduct request.
398func (client ProductAPIClient) ListByProductPreparer(ctx context.Context, resourceGroupName string, serviceName string, productID string, filter string, top *int32, skip *int32) (*http.Request, error) {
399	pathParameters := map[string]interface{}{
400		"productId":         autorest.Encode("path", productID),
401		"resourceGroupName": autorest.Encode("path", resourceGroupName),
402		"serviceName":       autorest.Encode("path", serviceName),
403		"subscriptionId":    autorest.Encode("path", client.SubscriptionID),
404	}
405
406	const APIVersion = "2019-01-01"
407	queryParameters := map[string]interface{}{
408		"api-version": APIVersion,
409	}
410	if len(filter) > 0 {
411		queryParameters["$filter"] = autorest.Encode("query", filter)
412	}
413	if top != nil {
414		queryParameters["$top"] = autorest.Encode("query", *top)
415	}
416	if skip != nil {
417		queryParameters["$skip"] = autorest.Encode("query", *skip)
418	}
419
420	preparer := autorest.CreatePreparer(
421		autorest.AsGet(),
422		autorest.WithBaseURL(client.BaseURI),
423		autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ApiManagement/service/{serviceName}/products/{productId}/apis", pathParameters),
424		autorest.WithQueryParameters(queryParameters))
425	return preparer.Prepare((&http.Request{}).WithContext(ctx))
426}
427
428// ListByProductSender sends the ListByProduct request. The method will close the
429// http.Response Body if it receives an error.
430func (client ProductAPIClient) ListByProductSender(req *http.Request) (*http.Response, error) {
431	sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client))
432	return autorest.SendWithSender(client, req, sd...)
433}
434
435// ListByProductResponder handles the response to the ListByProduct request. The method always
436// closes the http.Response Body.
437func (client ProductAPIClient) ListByProductResponder(resp *http.Response) (result APICollection, err error) {
438	err = autorest.Respond(
439		resp,
440		client.ByInspecting(),
441		azure.WithErrorUnlessStatusCode(http.StatusOK),
442		autorest.ByUnmarshallingJSON(&result),
443		autorest.ByClosing())
444	result.Response = autorest.Response{Response: resp}
445	return
446}
447
448// listByProductNextResults retrieves the next set of results, if any.
449func (client ProductAPIClient) listByProductNextResults(ctx context.Context, lastResults APICollection) (result APICollection, err error) {
450	req, err := lastResults.aPICollectionPreparer(ctx)
451	if err != nil {
452		return result, autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "listByProductNextResults", nil, "Failure preparing next results request")
453	}
454	if req == nil {
455		return
456	}
457	resp, err := client.ListByProductSender(req)
458	if err != nil {
459		result.Response = autorest.Response{Response: resp}
460		return result, autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "listByProductNextResults", resp, "Failure sending next results request")
461	}
462	result, err = client.ListByProductResponder(resp)
463	if err != nil {
464		err = autorest.NewErrorWithError(err, "apimanagement.ProductAPIClient", "listByProductNextResults", resp, "Failure responding to next results request")
465	}
466	return
467}
468
469// ListByProductComplete enumerates all values, automatically crossing page boundaries as required.
470func (client ProductAPIClient) ListByProductComplete(ctx context.Context, resourceGroupName string, serviceName string, productID string, filter string, top *int32, skip *int32) (result APICollectionIterator, err error) {
471	if tracing.IsEnabled() {
472		ctx = tracing.StartSpan(ctx, fqdn+"/ProductAPIClient.ListByProduct")
473		defer func() {
474			sc := -1
475			if result.Response().Response.Response != nil {
476				sc = result.page.Response().Response.Response.StatusCode
477			}
478			tracing.EndSpan(ctx, sc, err)
479		}()
480	}
481	result.page, err = client.ListByProduct(ctx, resourceGroupName, serviceName, productID, filter, top, skip)
482	return
483}
484